From 3e1b9761bf442a095f47a7dff48118b93204cdd8 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 22:35:34 +0100 Subject: [PATCH 001/435] Added alias dereferencing as described under https://github.com/ruby-ldap/ruby-net-ldap/issues/13 --- lib/net/ldap.rb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 680526da..7b5e1938 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -251,6 +251,12 @@ class LdapError < StandardError; end SearchScopes = [ SearchScope_BaseObject, SearchScope_SingleLevel, SearchScope_WholeSubtree ] + DerefAliases_Never = 0 + DerefAliases_Search = 1 + DerefAliases_Find = 2 + DerefAliases_Always = 3 + DerefAliasesArray = [ DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always ] + primitive = { 2 => :null } # UnbindRequest body constructed = { 0 => :array, # BindRequest @@ -995,7 +1001,7 @@ def rename(args) begin conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.rename(args) end ensure @@ -1396,7 +1402,11 @@ def search(args = {}) scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) - sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) + deref = args[:deref] || Net::LDAP::DerefAliases_Never + raise LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) + + sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) + # An interesting value for the size limit would be close to A/D's # built-in page limit of 1000 records, but openLDAP newer than version # 2.2.0 chokes on anything bigger than 126. You get a silent error that @@ -1436,7 +1446,7 @@ def search(args = {}) request = [ search_base.to_ber, scope.to_ber_enumerated, - 0.to_ber_enumerated, + deref.to_ber_enumerated, query_limit.to_ber, # size limit 0.to_ber, attributes_only.to_ber, From e05aaa9eee57b3be579c703399e20d6b059d5a09 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:00:35 +0100 Subject: [PATCH 002/435] Slight format cleanup --- lib/net/ldap.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 7b5e1938..560a7088 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1001,9 +1001,9 @@ def rename(args) begin conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) - end + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.rename(args) + end ensure conn.close if conn end @@ -1402,10 +1402,11 @@ def search(args = {}) scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) + deref = args[:deref] || Net::LDAP::DerefAliases_Never - raise LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) + raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) - sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) # An interesting value for the size limit would be close to A/D's # built-in page limit of 1000 records, but openLDAP newer than version From c86eb1ac8bd3b38d8cc7e9c90bb677408bb3bd2c Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:07:24 +0100 Subject: [PATCH 003/435] Indenting fixes --- lib/net/ldap.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 560a7088..84b63d68 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1001,9 +1001,9 @@ def rename(args) begin conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) - end + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.rename(args) + end ensure conn.close if conn end From 7e29e225956bab5761f10d1fa4a866716de47e48 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:10:05 +0100 Subject: [PATCH 004/435] More indent fixes --- lib/net/ldap.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 84b63d68..6662f60b 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1001,8 +1001,8 @@ def rename(args) begin conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.rename(args) end ensure conn.close if conn From 82620b67682a01c2bc2c141cb6084fad06929c78 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:12:52 +0100 Subject: [PATCH 005/435] Yet more indenting fixes --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 6662f60b..0697e252 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1002,7 +1002,7 @@ def rename(args) conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) + @result = conn.rename(args) end ensure conn.close if conn From 5193015b615e4e37c7acad170ce2256466ce5647 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:15:08 +0100 Subject: [PATCH 006/435] Replace tabs with spaces --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 0697e252..7148715c 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1002,7 +1002,7 @@ def rename(args) conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) + @result = conn.rename(args) end ensure conn.close if conn From 9ab84a06f1759594d7c755b3ca7b4cc66697f7c9 Mon Sep 17 00:00:00 2001 From: Niall Wilson Date: Fri, 28 Sep 2012 23:31:32 +0100 Subject: [PATCH 007/435] Added usage documentation --- lib/net/ldap.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 7148715c..718967cc 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -598,6 +598,8 @@ def open # Net::LDAP::SearchScope_WholeSubtree. Default is WholeSubtree.) # * :size (an integer indicating the maximum number of search entries to # return. Default is zero, which signifies no limit.) + # * :deref (one of: Net::LDAP::DerefAliases_Never, Net::LDAP::DerefAliases_Search, + # Net::LDAP::DerefAliases_Find, Net::LDAP::DerefAliases_Always. Default is Never.) # # #search queries the LDAP server and passes each entry to the # caller-supplied block, as an object of type Net::LDAP::Entry. If the @@ -1001,8 +1003,8 @@ def rename(args) begin conn = Connection.new(:host => @host, :port => @port, :encryption => @encryption) - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.rename(args) end ensure conn.close if conn @@ -1402,7 +1404,7 @@ def search(args = {}) scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) - sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) + sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) deref = args[:deref] || Net::LDAP::DerefAliases_Never raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) From 9b813472dea46d26e5a2794e4a2589b9bcf1de71 Mon Sep 17 00:00:00 2001 From: blair christensen Date: Mon, 14 Jan 2013 14:22:19 -0600 Subject: [PATCH 008/435] Update net-ldap.gemspec ASCIIfy characters that were leading to "invalid byte sequence in US-ASCII" errors --- net-ldap.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 03b8264f..05bb1715 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -14,9 +14,9 @@ subset of server features as well. Net::LDAP has been tested against modern popular LDAP servers including OpenLDAP and Active Directory. The current release is mostly compliant with -earlier versions of the IETF LDAP RFCs (2251–2256, 2829–2830, 3377, and 3771). +earlier versions of the IETF LDAP RFCs (2251-2256, 2829-2830, 3377, and 3771). Our roadmap for Net::LDAP 1.0 is to gain full client compliance with -the most recent LDAP RFCs (4510–4519, plutions of 4520–4532).} +the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif"] From 371b7f2775076d33b0c271910703362a30bf96b3 Mon Sep 17 00:00:00 2001 From: Julian Zinn Date: Sun, 27 Jan 2013 00:18:32 -0800 Subject: [PATCH 009/435] Unescape escaped filter characters in #to_ber --- lib/net/ldap/filter.rb | 12 ++++++------ spec/unit/ldap/filter_spec.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index f77c5e26..b38b13e9 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -291,11 +291,11 @@ def parse_ber(ber) case b.ber_identifier when 0x80 # context-specific primitive 0, SubstringFilter "initial" raise Net::LDAP::LdapError, "Unrecognized substring filter; bad initial value." if str.length > 0 - str += b + str += escape(b) when 0x81 # context-specific primitive 0, SubstringFilter "any" - str += "*#{b}" + str += "*#{escape(b)}" when 0x82 # context-specific primitive 0, SubstringFilter "final" - str += "*#{b}" + str += "*#{escape(b)}" final = true end } @@ -509,17 +509,17 @@ def to_ber first = nil ary.shift else - first = ary.shift.to_ber_contextspecific(0) + first = unescape(ary.shift).to_ber_contextspecific(0) end if ary.last.empty? last = nil ary.pop else - last = ary.pop.to_ber_contextspecific(2) + last = unescape(ary.pop).to_ber_contextspecific(2) end - seq = ary.map { |e| e.to_ber_contextspecific(1) } + seq = ary.map { |e| unescape(e).to_ber_contextspecific(1) } seq.unshift first if first seq.push last if last diff --git a/spec/unit/ldap/filter_spec.rb b/spec/unit/ldap/filter_spec.rb index 416be31c..5e4cb8a8 100644 --- a/spec/unit/ldap/filter_spec.rb +++ b/spec/unit/ldap/filter_spec.rb @@ -81,4 +81,35 @@ def eq(attribute, value) Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C" end end + + context 'with a well-known BER string' do + ber = "\xa4\x2d" \ + "\x04\x0b" "objectclass" \ + "\x30\x1e" \ + "\x80\x08" "foo" "*\\" "bar" \ + "\x81\x08" "foo" "*\\" "bar" \ + "\x82\x08" "foo" "*\\" "bar" + + describe "<- .to_ber" do + [ + "foo" "\\2A\\5C" "bar", + "foo" "\\2a\\5c" "bar", + "foo" "\\2A\\5c" "bar", + "foo" "\\2a\\5C" "bar" + ].each do |escaped| + it 'unescapes escaped characters' do + filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}") + filter.to_ber.should == ber + end + end + end + + describe '<- .parse_ber' do + it 'escapes characters' do + escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar") + filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) + filter.to_s.should == "(objectclass=#{escaped}*#{escaped}*#{escaped})" + end + end + end end From 3f37bbcf24bea63c0b6c0373cad9fea3196135fb Mon Sep 17 00:00:00 2001 From: Brian Weaver Date: Wed, 13 Feb 2013 10:40:54 -0500 Subject: [PATCH 010/435] Fixes an error when following referrals When following referrals in search results an error occurs due to an unreferrenced variable. The actual value is on the pdu object. --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 680526da..ffbd5d74 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1481,7 +1481,7 @@ def search(args = {}) when 5 # search-result result_pdu = pdu controls = pdu.result_controls - if return_referrals && result_code == 10 + if return_referrals && pdu.result_code == 10 if block_given? se = Net::LDAP::Entry.new se[:search_referrals] = (pdu.search_referrals || []) From 6dd88b26105d32cdf46d6742cd6186437144bbcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ho=CC=88ltje?= Date: Fri, 1 Mar 2013 14:54:52 -0500 Subject: [PATCH 011/435] Moved VERSION into a single file You can now update VERSION via just one file: lib/net/ldap/version.rb This makes maintenance easier. --- Manifest.txt | 1 + lib/net/ber.rb | 4 +++- lib/net/ldap.rb | 2 +- lib/net/ldap/version.rb | 5 +++++ lib/net/snmp.rb | 4 +++- net-ldap.gemspec | 6 +++++- 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 lib/net/ldap/version.rb diff --git a/Manifest.txt b/Manifest.txt index c389dfb3..5abc1459 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -25,6 +25,7 @@ lib/net/ldap/entry.rb lib/net/ldap/filter.rb lib/net/ldap/password.rb lib/net/ldap/pdu.rb +lib/net/ldap/version.rb lib/net/snmp.rb net-ldap.gemspec spec/integration/ssl_ber_spec.rb diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 14454702..f0e825a9 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -1,4 +1,6 @@ # -*- ruby encoding: utf-8 -*- +require 'net/ldap/version' + module Net # :nodoc: ## # == Basic Encoding Rules (BER) Support Module @@ -106,7 +108,7 @@ module Net # :nodoc: # BMPStringC30: 62 (0x3e, 0b00111110) # module BER - VERSION = '0.4.0' + VERSION = Net::LDAP::VERSION ## # Used for BER-encoding the length and content bytes of a Fixnum integer diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 680526da..468db157 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -23,6 +23,7 @@ class LDAP require 'net/ldap/dataset' require 'net/ldap/password' require 'net/ldap/entry' +require 'net/ldap/version' # == Quick-start for the Impatient # === Quick Example of a user-authentication against an LDAP directory: @@ -241,7 +242,6 @@ class LDAP # and then keeps it open while it executes a user-supplied block. # Net::LDAP#open closes the connection on completion of the block. class Net::LDAP - VERSION = "0.4.0" class LdapError < StandardError; end diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb new file mode 100644 index 00000000..da3b2106 --- /dev/null +++ b/lib/net/ldap/version.rb @@ -0,0 +1,5 @@ +module Net + class LDAP + VERSION = "0.4.0" + end +end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 98f2df34..3f9e5fb1 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -1,8 +1,10 @@ # -*- ruby encoding: utf-8 -*- +require 'net/ldap/version' + # :stopdoc: module Net class SNMP - VERSION = '0.4.0' + VERSION = Net::LDAP::VERSION AsnSyntax = Net::BER.compile_syntax({ :application => { diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 03b8264f..c0e9c73c 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -1,7 +1,11 @@ # -*- encoding: utf-8 -*- +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'net/ldap/version' + Gem::Specification.new do |s| s.name = %q{net-ldap} - s.version = "0.4.0" + s.version = Net::LDAP::VERSION s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler"] From b6c6dda7ea5f72c9c40ea67a62a68c00fc3c0870 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Tue, 12 Mar 2013 13:53:43 +0900 Subject: [PATCH 012/435] Fix Invalid examples 1. String#encode should not fail if given an invalid code like '\x81' This is because this problem has been resolved by #41. 2. Net::LDAP#search should return a boolean if return_result is false. --- spec/unit/ber/ber_spec.rb | 4 ++-- spec/unit/ldap/search_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 10288d09..994c2312 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -89,9 +89,9 @@ ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16" end - it "should fail on strings that can not be converted to UTF-8" do + it "should not fail on strings that can not be converted to UTF-8" do error = Encoding::UndefinedConversionError - lambda {"\x81".to_ber }.should raise_exception(error) + lambda {"\x81".to_ber }.should_not raise_exception(error) end end end diff --git a/spec/unit/ldap/search_spec.rb b/spec/unit/ldap/search_spec.rb index 8f9446ca..5d06a88e 100644 --- a/spec/unit/ldap/search_spec.rb +++ b/spec/unit/ldap/search_spec.rb @@ -3,7 +3,7 @@ describe Net::LDAP, "search method" do class FakeConnection def search(args) - OpenStruct.new(:result_code => 1, :message => "error") + OpenStruct.new(:result_code => 1, :message => "error", :success? => false) end end @@ -22,7 +22,7 @@ def search(args) context "when :return_result => false" do it "should return false upon error" do result = @connection.search(:return_result => false) - result.result_code.should == 1 + result.should be_false end end From 8759acb75919d017db06898e6d1ce708c27cb24a Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 13 Mar 2013 16:35:13 +0900 Subject: [PATCH 013/435] Adopt Travis-CI --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..3e1e6f43 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: ruby +rvm: + - 1.8.7 + - 1.9.2 + - 1.9.3 +script: bundle exec rake spec From c1166278439ecff5c8092dc42ad7ac8aa239cdca Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 13 Mar 2013 16:46:29 +0900 Subject: [PATCH 014/435] Add status image to README --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 25f9078f..b0c93bc4 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -= Net::LDAP for Ruby += Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap]] == Description From 2e1d78d0d8c130a37f1d3acb53b006f85e3b6de4 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 13 Mar 2013 16:49:49 +0900 Subject: [PATCH 015/435] Update README.rdoc Fix typo --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index b0c93bc4..115d2e2c 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -= Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap]] += Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap] == Description From 7438a2ab45b6aabfbcb1b078fc72419d7b0442ba Mon Sep 17 00:00:00 2001 From: Denis Knauf Date: Sat, 16 Mar 2013 13:10:02 +0100 Subject: [PATCH 016/435] One LdapError-class => Specific errors for every exception. --- lib/net/ldap.rb | 73 +++++++++++++++++++++++++++------------- lib/net/ldap/entry.rb | 2 +- lib/net/ldap/filter.rb | 16 ++++----- lib/net/ldap/password.rb | 2 +- test/test_filter.rb | 4 +-- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 680526da..559c9e3a 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -244,6 +244,33 @@ class Net::LDAP VERSION = "0.4.0" class LdapError < StandardError; end + class AlreadyOpenedError < LdapError; end + class SocketError < LdapError; end + class ConnectionRefusedError < LdapError; end + class NoOpenSSLError < LdapError; end + class NoStartTLSResultError < LdapError; end + class StartTLSError < LdapError; end + class EncryptionUnsupportedError < LdapError; end + class EncMethodUnsupportedError < LdapError; end + class AuthMethodUnsupportedError < LdapError; end + class BindingInformationInvalidError < LdapError; end + class NoBindResultError < LdapError; end + class SASLChallengeOverflowError < LdapError; end + class SearchSizeInvalidError < LdapError; end + class SearchScopeInvalidError < LdapError; end + class ResponseTypeInvalidError < LdapError; end + class ResponseMissingOrInvalidError < LdapError; end + class EmptyDNError < LdapError; end + class HashTypeUnsupportedError < LdapError; end + class OperatorError < LdapError; end + class SubstringFilterError < LdapError; end + class SearchFilterError < LdapError; end + class BERInvalidError < LdapError; end + class SearchFilterTypeUnknownError < LdapError; end + class BadAttributeError < LdapError; end + class FilterTypeUnknownError < LdapError; end + class FilterSyntaxInvalidError < LdapError; end + class EntryOverflowError < LdapError; end SearchScope_BaseObject = 0 SearchScope_SingleLevel = 1 @@ -563,7 +590,7 @@ def open # anything with the bind results. We then pass self to the caller's # block, where he will execute his LDAP operations. Of course they will # all generate auth failures if the bind was unsuccessful. - raise Net::LDAP::LdapError, "Open already in progress" if @open_connection + raise Net::LDAP::AlreadyOpenedError, "Open already in progress" if @open_connection begin @open_connection = Net::LDAP::Connection.new(:host => @host, @@ -1134,9 +1161,9 @@ def initialize(server) begin @conn = TCPSocket.new(server[:host], server[:port]) rescue SocketError - raise Net::LDAP::LdapError, "No such address or other socket error." + raise Net::LDAP::SocketError, "No such address or other socket error." rescue Errno::ECONNREFUSED - raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." + raise Net::LDAP::ConnectionRefusedError, "Server #{server[:host]} refused connection on port #{server[:port]}." end if server[:encryption] @@ -1153,7 +1180,7 @@ def getbyte end def self.wrap_with_ssl(io) - raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL + raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new conn = OpenSSL::SSL::SSLSocket.new(io, ctx) conn.connect @@ -1202,16 +1229,16 @@ def setup_encryption(args) request_pkt = [msgid, request].to_ber_sequence @conn.write request_pkt be = @conn.read_ber(Net::LDAP::AsnSyntax) - raise Net::LDAP::LdapError, "no start_tls result" if be.nil? + raise Net::LDAP::NoStartTLSResultError, "no start_tls result" if be.nil? pdu = Net::LDAP::PDU.new(be) - raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? + raise Net::LDAP::NoStartTLSResultError, "no start_tls result" if pdu.nil? if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn) else - raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" + raise Net::LDAP::StartTLSError, "start_tls failed: #{pdu.result_code}" end else - raise Net::LDAP::LdapError, "unsupported encryption method #{args[:method]}" + raise Net::LDAP::EncryptionUnsupportedError, "unsupported encryption method #{args[:method]}" end end @@ -1239,7 +1266,7 @@ def bind(auth) elsif meth == :gss_spnego bind_gss_spnego(auth) else - raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" + raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})" end end @@ -1254,7 +1281,7 @@ def bind_simple(auth) ["", ""] end - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) msgid = next_msgid.to_ber request = [LdapVersion.to_ber, user.to_ber, @@ -1262,7 +1289,7 @@ def bind_simple(auth) request_pkt = [msgid, request].to_ber_sequence @conn.write request_pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::NoBindResultError, "no bind result" pdu end @@ -1291,7 +1318,7 @@ def bind_simple(auth) def bind_sasl(auth) mech, cred, chall = auth[:mechanism], auth[:initial_credential], auth[:challenge_response] - raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall) n = 0 loop { @@ -1301,9 +1328,9 @@ def bind_sasl(auth) request_pkt = [msgid, request].to_ber_sequence @conn.write request_pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::NoBindResultError, "no bind result" return pdu unless pdu.result_code == 14 # saslBindInProgress - raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) cred = chall.call(pdu.result_server_sasl_creds) } @@ -1327,7 +1354,7 @@ def bind_gss_spnego(auth) require 'ntlm' user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) nego = proc { |challenge| t2_msg = NTLM::Message.parse(challenge) @@ -1389,12 +1416,12 @@ def search(args = {}) search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber} return_referrals = args && args[:return_referrals] == true sizelimit = (args && args[:size].to_i) || 0 - raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0 + raise Net::LDAP::SearchSizeInvalidError, "invalid search-size" unless sizelimit >= 0 paged_searches_supported = (args && args[:paged_searches_supported]) attributes_only = (args and args[:attributes_only] == true) scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree - raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + raise Net::LDAP::SearchScopeInvalidError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) # An interesting value for the size limit would be close to A/D's @@ -1490,7 +1517,7 @@ def search(args = {}) end break else - raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" + raise Net::LDAP::ResponseTypeInvalidError, "invalid response-type in search: #{pdu.app_tag}" end end @@ -1563,7 +1590,7 @@ def modify(args) pkt = [ next_msgid.to_ber, request ].to_ber_sequence @conn.write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" pdu end @@ -1576,7 +1603,7 @@ def modify(args) # to the error message and the matched-DN returned by the server. #++ def add(args) - add_dn = args[:dn] or raise Net::LDAP::LdapError, "Unable to add empty DN" + add_dn = args[:dn] or raise Net::LDAP::EmptyDNError, "Unable to add empty DN" add_attrs = [] a = args[:attributes] and a.each { |k, v| add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence @@ -1589,7 +1616,7 @@ def add(args) (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 9) or - raise Net::LDAP::LdapError, "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" pdu end @@ -1611,7 +1638,7 @@ def rename(args) (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == 13) or - raise Net::LDAP::LdapError.new( "response missing or invalid" ) + raise Net::LDAP::ResponseMissingOrInvalidError.new( "response missing or invalid" ) pdu end @@ -1626,7 +1653,7 @@ def delete(args) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence @conn.write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" pdu end diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index 616ffe7f..18bfd053 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -71,7 +71,7 @@ def from_single_ldif_string(ldif) return nil if ds.empty? - raise Net::LDAP::LdapError, "Too many LDIF entries" unless ds.size == 1 + raise Net::LDAP::EntryOverflowError, "Too many LDIF entries" unless ds.size == 1 entry = ds.to_entries.first diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index f77c5e26..3f1ff6dd 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -27,7 +27,7 @@ class Net::LDAP::Filter def initialize(op, left, right) #:nodoc: unless FilterTypes.include?(op) - raise Net::LDAP::LdapError, "Invalid or unsupported operator #{op.inspect} in LDAP Filter." + raise Net::LDAP::OperatorError, "Invalid or unsupported operator #{op.inspect} in LDAP Filter." end @op = op @left = left @@ -290,7 +290,7 @@ def parse_ber(ber) ber.last.each { |b| case b.ber_identifier when 0x80 # context-specific primitive 0, SubstringFilter "initial" - raise Net::LDAP::LdapError, "Unrecognized substring filter; bad initial value." if str.length > 0 + raise Net::LDAP::SubstringFilterError, "Unrecognized substring filter; bad initial value." if str.length > 0 str += b when 0x81 # context-specific primitive 0, SubstringFilter "any" str += "*#{b}" @@ -309,7 +309,7 @@ def parse_ber(ber) # call to_s to get rid of the BER-identifiedness of the incoming string. present?(ber.to_s) when 0xa9 # context-specific constructed 9, "extensible comparison" - raise Net::LDAP::LdapError, "Invalid extensible search filter, should be at least two elements" if ber.size<2 + raise Net::LDAP::SearchFilterError, "Invalid extensible search filter, should be at least two elements" if ber.size<2 # Reassembles the extensible filter parts # (["sn", "2.4.6.8.10", "Barbara Jones", '1']) @@ -330,7 +330,7 @@ def parse_ber(ber) ex(attribute, value) else - raise Net::LDAP::LdapError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter." + raise Net::LDAP::BERInvalidError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter." end end @@ -357,7 +357,7 @@ def parse_ldap_filter(obj) when 0xa3 # equalityMatch. context-specific constructed 3. eq(obj[0], obj[1]) else - raise Net::LDAP::LdapError, "Unknown LDAP search-filter type: #{obj.ber_identifier}" + raise Net::LDAP::SearchFilterTypeUnknownError, "Unknown LDAP search-filter type: #{obj.ber_identifier}" end end end @@ -534,7 +534,7 @@ def to_ber seq = [] unless @left =~ /^([-;\w]*)(:dn)?(:(\w+|[.\w]+))?$/ - raise Net::LDAP::LdapError, "Bad attribute #{@left}" + raise Net::LDAP::BadAttributeError, "Bad attribute #{@left}" end type, dn, rule = $1, $2, $4 @@ -641,7 +641,7 @@ def match(entry) l = entry[@left] and l = Array(l) and l.index(@right) end else - raise Net::LDAP::LdapError, "Unknown filter type in match: #{@op}" + raise Net::LDAP::FilterTypeUnknownError, "Unknown filter type in match: #{@op}" end end @@ -674,7 +674,7 @@ def parse(ldap_filter_string) def initialize(str) require 'strscan' # Don't load strscan until we need it. @filter = parse(StringScanner.new(str)) - raise Net::LDAP::LdapError, "Invalid filter syntax." unless @filter + raise Net::LDAP::FilterSyntaxInvalidError, "Invalid filter syntax." unless @filter end ## diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 9c873029..c7ca8e05 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -29,7 +29,7 @@ def generate(type, str) srand; salt = (rand * 1000).to_i.to_s attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! else - raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" + raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})" end return attribute_value end diff --git a/test/test_filter.rb b/test/test_filter.rb index 03436e03..1ac40ed8 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -9,11 +9,11 @@ def test_bug_7534_rfc2254 end def test_invalid_filter_string - assert_raises(Net::LDAP::LdapError) { Filter.from_rfc2254("") } + assert_raises(Net::LDAP::FilterSyntaxInvalidError) { Filter.from_rfc2254("") } end def test_invalid_filter - assert_raises(Net::LDAP::LdapError) { + assert_raises(Net::LDAP::OperatorError) { # This test exists to prove that our constructor blocks unknown filter # types. All filters must be constructed using helpers. Filter.__send__(:new, :xx, nil, nil) From 251735bacc8483bbc3aa487cffcca200e6bbe0e7 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 12 Apr 2013 20:48:28 +0900 Subject: [PATCH 017/435] Add support version of ruby --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3e1e6f43..ae42b003 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,4 +3,10 @@ rvm: - 1.8.7 - 1.9.2 - 1.9.3 + - 2.0.0 + - jruby-18mode + - jruby-19mode + - rbx-18mode + - rbx-19mode + - ree script: bundle exec rake spec From fe95779fac9ed761c00712403ed0a186a41fd5ec Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 12 Apr 2013 20:54:07 +0900 Subject: [PATCH 018/435] Change the value of source in Gemfile because deprecated --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index e45e65f8..851fabc2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,2 @@ -source :rubygems +source 'https://rubygems.org' gemspec From 234daf900161b529c109a5377e9cabec2baf4213 Mon Sep 17 00:00:00 2001 From: Lucy Fu Date: Fri, 19 Apr 2013 14:12:34 -0400 Subject: [PATCH 019/435] Let Net::BER::BerIdentifiedString fall back if string cannot be encoded. --- lib/net/ber.rb | 2 +- spec/unit/ber/ber_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 14454702..59670f9c 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -296,7 +296,7 @@ class Net::BER::BerIdentifiedString < String def initialize args super args # LDAP uses UTF-8 encoded strings - force_encoding('UTF-8') if respond_to?(:encoding) + self.encode('UTF-8') if self.respond_to?(:encoding) rescue self end end diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 10288d09..5f9dbd2e 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -112,3 +112,30 @@ end end end + +describe Net::BER::BerIdentifiedString do + describe "initialize" do + subject { Net::BER::BerIdentifiedString.new(data) } + + context "binary data" do + let(:data) { ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") } + + its(:valid_encoding?) { should be_true } + specify { subject.encoding.name.should == "ASCII-8BIT" } + end + + context "ascii data in UTF-8" do + let(:data) { "some text".force_encoding("UTF-8") } + + its(:valid_encoding?) { should be_true } + specify { subject.encoding.name.should == "UTF-8" } + end + + context "UTF-8 data in UTF-8" do + let(:data) { ["e4b8ad"].pack("H*").force_encoding("UTF-8") } + + its(:valid_encoding?) { should be_true } + specify { subject.encoding.name.should == "UTF-8" } + end + end +end From e07b7ddd926f82f61914b920da67adff6b8c636c Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 15 May 2013 00:45:32 +0900 Subject: [PATCH 020/435] Add spec to reproduce FilterPraser.parse fails with multibyte char --- spec/unit/ldap/filter_parser_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 spec/unit/ldap/filter_parser_spec.rb diff --git a/spec/unit/ldap/filter_parser_spec.rb b/spec/unit/ldap/filter_parser_spec.rb new file mode 100644 index 00000000..f3ad441f --- /dev/null +++ b/spec/unit/ldap/filter_parser_spec.rb @@ -0,0 +1,20 @@ +# encoding: utf-8 +require 'spec_helper' + +describe Net::LDAP::Filter::FilterParser do + + describe "#parse" do + context "Given ASCIIs as filter string" do + let(:filter_string) { "(&(objectCategory=person)(objectClass=user))" } + specify "should generate filter object" do + expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter + end + end + context "Given string including multibyte chars as filter string" do + let(:filter_string) { "(cn=名前)" } + specify "should generate filter object" do + expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter + end + end + end +end From d5a6c039a8954cec91e1e84d0d55899d7af7cf36 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Thu, 16 May 2013 15:02:08 +0900 Subject: [PATCH 021/435] Simplify an example for FilterParser --- spec/unit/ldap/filter_parser_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/unit/ldap/filter_parser_spec.rb b/spec/unit/ldap/filter_parser_spec.rb index f3ad441f..e34828eb 100644 --- a/spec/unit/ldap/filter_parser_spec.rb +++ b/spec/unit/ldap/filter_parser_spec.rb @@ -5,7 +5,7 @@ describe "#parse" do context "Given ASCIIs as filter string" do - let(:filter_string) { "(&(objectCategory=person)(objectClass=user))" } + let(:filter_string) { "(cn=name)" } specify "should generate filter object" do expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter end From 4e882488ab173f695dd0ee694c389c5ea6db092d Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Thu, 16 May 2013 15:02:32 +0900 Subject: [PATCH 022/435] Fix: Fails to parser when given string includes multibyte chars. Net::LDAP::Filter::FilterParser fails to parse when a given string includes multibyte chars such as Japanese characters. But this should support it according to RFC-2254. This commit is to fix this failure. --- lib/net/ldap/filter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index f77c5e26..89d173b1 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -755,7 +755,7 @@ def parse_filter_branch(scanner) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) - if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|\\[a-fA-F\d]{2})+/) + if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) # 20100313 AZ: Assumes that "(uid=george*)" is the same as # "(uid=george* )". The standard doesn't specify, but I can find # no examples that suggest otherwise. From a8d0bbe81373c8d1f0ce50e7a14b65022fdd3dc2 Mon Sep 17 00:00:00 2001 From: Jason Franklin Date: Wed, 5 Jun 2013 13:22:58 +0200 Subject: [PATCH 023/435] Catch Encoding::ConverterNotFoundError Some binary format on Active Directory can raise "Encoding::ConverterNotFoundError". Signed-off-by: Jason Franklin --- lib/net/ber/core_ext/string.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ber/core_ext/string.rb b/lib/net/ber/core_ext/string.rb index 26530bff..a0fcfb46 100644 --- a/lib/net/ber/core_ext/string.rb +++ b/lib/net/ber/core_ext/string.rb @@ -32,6 +32,8 @@ def raw_utf8_encoded self.encode('UTF-8').force_encoding('ASCII-8BIT') rescue Encoding::UndefinedConversionError self + rescue Encoding::ConverterNotFoundError + return self end else self From ba713927fd16367d316ddd23dc6678caba18996a Mon Sep 17 00:00:00 2001 From: Rory O'Connell Date: Mon, 22 Jul 2013 10:31:56 -0700 Subject: [PATCH 024/435] Temporary fix for gemspec for people pointing to Git --- net-ldap.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 8bb5c041..15350bbd 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -23,7 +23,7 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif"] + s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] s.homepage = %q{http://github.com.org/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 567ae54eba06744198d05bd10a8af94b81e3c6ff Mon Sep 17 00:00:00 2001 From: Rory O'Connell Date: Mon, 22 Jul 2013 21:00:17 -0700 Subject: [PATCH 025/435] Updating travis with new ruby requirements --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index ae42b003..9e097a28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,7 @@ language: ruby rvm: - - 1.8.7 - - 1.9.2 - 1.9.3 - 2.0.0 - - jruby-18mode - jruby-19mode - - rbx-18mode - rbx-19mode - - ree script: bundle exec rake spec From 1115cf93142de8b7215beaf49706cdde2d44ef78 Mon Sep 17 00:00:00 2001 From: Rory O'Connell Date: Mon, 22 Jul 2013 21:23:00 -0700 Subject: [PATCH 026/435] Updating readme with ruby version, removing ancient setup instructions --- README.rdoc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.rdoc b/README.rdoc index 115d2e2c..32c9f6e9 100644 --- a/README.rdoc +++ b/README.rdoc @@ -30,7 +30,7 @@ See Net::LDAP for documentation and usage samples. == Requirements -Net::LDAP requires a Ruby 1.8.7 interpreter or better. +Net::LDAP requires a Ruby 1.9.3 compatible interpreter or better. == Install @@ -42,11 +42,6 @@ sources. Simply require either 'net-ldap' or 'net/ldap'. -For non-RubyGems installations of Net::LDAP, you can use Minero Aoki's -{setup.rb}[http://i.loveruby.net/en/projects/setup/] as the layout of -Net::LDAP is compliant. The setup installer is not included in the -Net::LDAP repository. - :include: Contributors.rdoc :include: License.rdoc From 40846cb7d0f0db8e8218c0dc7b40ae65df48ec90 Mon Sep 17 00:00:00 2001 From: Rory O'Connell Date: Mon, 22 Jul 2013 21:23:29 -0700 Subject: [PATCH 027/435] Updating history with latest PR descriptions --- History.rdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/History.rdoc b/History.rdoc index 1032745b..e0ee3e0a 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,15 @@ +=== Net::LDAP 0.5.0 / 2013-07-22 +* Major changes: + * Required Ruby version is >=1.9.3 +* Major enhancements: + * Added alias dereferencing (@ngwilson) + * BER now unescapes characters that are already escaped in the source string (@jzinn) + * BerIdentifiedString will now fall back to ASCII-8 encoding if the source Ruby object cannot be encoded in UTF-8 (@lfu) +* Bug fixes: + * Fixed nil variable error when following a reference response (@cmdrclueless) + * Fixed FilterParser unable to parse multibyte strings (@satoryu) + * Return ConverterNotFound when dealing with a potentially corrupt data response (@jamuc) + === Net::LDAP 0.3.1 / 2012-02-15 * Bug Fixes: * Bundler should now work again From bbef82f22494864f5c0e53d4dffb21cead3fc274 Mon Sep 17 00:00:00 2001 From: Rory O'Connell Date: Mon, 22 Jul 2013 21:43:46 -0700 Subject: [PATCH 028/435] bumping version --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index da3b2106..f9fdaf05 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.4.0" + VERSION = "0.5.0" end end From 2be5f17385a3a2c316762f31656a2915c9b9a4af Mon Sep 17 00:00:00 2001 From: sahglie Date: Wed, 4 Sep 2013 21:59:42 -0700 Subject: [PATCH 029/435] colons are ':' valid filter characters --- lib/net/ldap/filter.rb | 2 +- spec/unit/ldap/filter_parser_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 66610010..b4999ec8 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -755,7 +755,7 @@ def parse_filter_branch(scanner) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) - if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) + if value = scanner.scan(/(?:[-\w*.+:@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) # 20100313 AZ: Assumes that "(uid=george*)" is the same as # "(uid=george* )". The standard doesn't specify, but I can find # no examples that suggest otherwise. diff --git a/spec/unit/ldap/filter_parser_spec.rb b/spec/unit/ldap/filter_parser_spec.rb index e34828eb..c65c615a 100644 --- a/spec/unit/ldap/filter_parser_spec.rb +++ b/spec/unit/ldap/filter_parser_spec.rb @@ -16,5 +16,11 @@ expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter end end + context "Given string including colons ':'" do + let(:filter_string) { "(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" } + specify "should generate filter object" do + expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter + end + end end end From 017223d10ab21a94868ee7477022dc8237736269 Mon Sep 17 00:00:00 2001 From: Xin Li Date: Thu, 13 Feb 2014 17:39:16 -0800 Subject: [PATCH 030/435] Use 16 bytes secure random instead of a number from 0 to 999. This increases entropy in the salt from about 10 bits to 128 bits. Reported by: Pierre Carrier Security: CVE-2014-0083 --- lib/net/ldap/password.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 9c873029..929f55ec 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -2,6 +2,7 @@ require 'digest/sha1' require 'digest/md5' require 'base64' +require 'securerandom' class Net::LDAP::Password class << self @@ -26,7 +27,7 @@ def generate(type, str) when :sha attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! when :ssha - srand; salt = (rand * 1000).to_i.to_s + salt = SecureRandom.random_bytes(16) attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! else raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" From 210585e458ef809b949c25b1c4592fbd78a1222f Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Wed, 19 Mar 2014 11:12:09 +0100 Subject: [PATCH 031/435] update flexmock to 1.3, update some hoe attributes --- Manifest.txt | 5 +++++ Rakefile | 7 ++++--- net-ldap.gemspec | 7 ++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Manifest.txt b/Manifest.txt index 5abc1459..86cbea5f 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,6 +1,8 @@ .autotest .rspec +.travis.yml Contributors.rdoc +Gemfile Hacking.rdoc History.rdoc License.rdoc @@ -32,10 +34,13 @@ spec/integration/ssl_ber_spec.rb spec/spec.opts spec/spec_helper.rb spec/unit/ber/ber_spec.rb +spec/unit/ber/core_ext/array_spec.rb spec/unit/ber/core_ext/string_spec.rb spec/unit/ldap/dn_spec.rb spec/unit/ldap/entry_spec.rb +spec/unit/ldap/filter_parser_spec.rb spec/unit/ldap/filter_spec.rb +spec/unit/ldap/search_spec.rb spec/unit/ldap_spec.rb test/common.rb test/test_entry.rb diff --git a/Rakefile b/Rakefile index b30f529e..86c8af9e 100644 --- a/Rakefile +++ b/Rakefile @@ -8,7 +8,7 @@ Hoe.plugin :git Hoe.plugin :gemspec Hoe.spec 'net-ldap' do |spec| - spec.rubyforge_name = spec.name + # spec.rubyforge_name = spec.name spec.developer("Francis Cianfrocca", "blackhedd@rubyforge.org") spec.developer("Emiel van de Laar", "gemiel@gmail.com") @@ -19,7 +19,8 @@ Hoe.spec 'net-ldap' do |spec| spec.remote_rdoc_dir = '' spec.rsync_args << ' --exclude=statsvn/' - spec.url = %W(http://rubyldap.com/ https://github.com/ruby-ldap/ruby-net-ldap) + spec.urls = ['http://rubyldap.com/ https://github.com/ruby-ldap/ruby-net-ldap'] + spec.licenses = ['MIT'] spec.history_file = 'History.rdoc' spec.readme_file = 'README.rdoc' @@ -29,7 +30,7 @@ Hoe.spec 'net-ldap' do |spec| spec.extra_dev_deps << [ "hoe-git", "~> 1" ] spec.extra_dev_deps << [ "hoe-gemspec", "~> 1" ] spec.extra_dev_deps << [ "metaid", "~> 1" ] - spec.extra_dev_deps << [ "flexmock", "~> 0.9.0" ] + spec.extra_dev_deps << [ "flexmock", "~> 1.3.0" ] spec.extra_dev_deps << [ "rspec", "~> 2.0" ] spec.clean_globs << "coverage" diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 15350bbd..aa263b15 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -6,6 +6,7 @@ require 'net/ldap/version' Gem::Specification.new do |s| s.name = %q{net-ldap} s.version = Net::LDAP::VERSION + s.license = "MIT" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler"] @@ -40,14 +41,14 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, ["~> 1"]) - s.add_development_dependency(%q, ["~> 0.9.0"]) + s.add_development_dependency(%q, [">= 1.3.0"]) s.add_development_dependency(%q, ["~> 2.0"]) s.add_development_dependency(%q, [">= 2.9.1"]) else s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 0.9.0"]) + s.add_dependency(%q, [">= 1.3.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) end @@ -55,7 +56,7 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 0.9.0"]) + s.add_dependency(%q, [">= 1.3.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) end From 4f837ca6b8c0828d1bd7e2b8099e2f645863bb7e Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Wed, 19 Mar 2014 11:27:45 +0100 Subject: [PATCH 032/435] update url parameter in gemspec file --- Rakefile | 5 +++-- net-ldap.gemspec | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index 86c8af9e..159a8a09 100644 --- a/Rakefile +++ b/Rakefile @@ -15,11 +15,12 @@ Hoe.spec 'net-ldap' do |spec| spec.developer("Rory O'Connell", "rory.ocon@gmail.com") spec.developer("Kaspar Schiess", "kaspar.schiess@absurd.li") spec.developer("Austin Ziegler", "austin@rubyforge.org") + spec.developer("Michael Schaarschmidt", "michael@schaaryworks.com") spec.remote_rdoc_dir = '' spec.rsync_args << ' --exclude=statsvn/' - spec.urls = ['http://rubyldap.com/ https://github.com/ruby-ldap/ruby-net-ldap'] + spec.urls = %w(http://rubyldap.com/' 'https://github.com/ruby-ldap/ruby-net-ldap) spec.licenses = ['MIT'] spec.history_file = 'History.rdoc' @@ -30,7 +31,7 @@ Hoe.spec 'net-ldap' do |spec| spec.extra_dev_deps << [ "hoe-git", "~> 1" ] spec.extra_dev_deps << [ "hoe-gemspec", "~> 1" ] spec.extra_dev_deps << [ "metaid", "~> 1" ] - spec.extra_dev_deps << [ "flexmock", "~> 1.3.0" ] + spec.extra_dev_deps << [ "flexmock", ">= 1.3.0" ] spec.extra_dev_deps << [ "rspec", "~> 2.0" ] spec.clean_globs << "coverage" diff --git a/net-ldap.gemspec b/net-ldap.gemspec index aa263b15..01545adf 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.license = "MIT" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler"] + s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler", "Michael Schaarschmidt"] s.date = %q{2012-02-28} s.description = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for From 51a7ea4f23432b808dec207d106173ba8d124233 Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Wed, 19 Mar 2014 11:28:43 +0100 Subject: [PATCH 033/435] push version to 0.5.1 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index f9fdaf05..1c5566e6 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.5.0" + VERSION = "0.5.1" end end From 17607c6dc8ea90c4a0a23f64e6588433e4b0264c Mon Sep 17 00:00:00 2001 From: Kuldeep Aggarwal Date: Tue, 25 Mar 2014 23:33:52 +0530 Subject: [PATCH 034/435] indent file, and use multiple conditions in one line --- lib/net/ldap/filter.rb | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 66610010..904ad16a 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -65,22 +65,22 @@ def eq(attribute, value) new(:eq, attribute, value) end - ## - # Creates a Filter object indicating a binary comparison. - # this prevents the search data from being forced into a UTF-8 string. - # - # This is primarily used for Microsoft Active Directory to compare - # GUID values. - # - # # for guid represented as hex charecters - # guid = "6a31b4a12aa27a41aca9603f27dd5116" - # guid_bin = [guid].pack("H*") - # f = Net::LDAP::Filter.bineq("objectGUID", guid_bin) - # - # This filter does not perform any escaping. - def bineq(attribute, value) - new(:bineq, attribute, value) - end + ## + # Creates a Filter object indicating a binary comparison. + # this prevents the search data from being forced into a UTF-8 string. + # + # This is primarily used for Microsoft Active Directory to compare + # GUID values. + # + # # for guid represented as hex charecters + # guid = "6a31b4a12aa27a41aca9603f27dd5116" + # guid_bin = [guid].pack("H*") + # f = Net::LDAP::Filter.bineq("objectGUID", guid_bin) + # + # This filter does not perform any escaping. + def bineq(attribute, value) + new(:bineq, attribute, value) + end ## # Creates a Filter object indicating extensible comparison. This Filter @@ -414,10 +414,8 @@ def to_raw_rfc2254 case @op when :ne "!(#{@left}=#{@right})" - when :eq + when :eq, :bineq "#{@left}=#{@right}" - when :bineq - "#{@left}=#{@right}" when :ex "#{@left}:=#{@right}" when :ge @@ -527,9 +525,9 @@ def to_ber else # equality [@left.to_s.to_ber, unescape(@right).to_ber].to_ber_contextspecific(3) end - when :bineq - # make sure data is not forced to UTF-8 - [@left.to_s.to_ber, unescape(@right).to_ber_bin].to_ber_contextspecific(3) + when :bineq + # make sure data is not forced to UTF-8 + [@left.to_s.to_ber, unescape(@right).to_ber_bin].to_ber_contextspecific(3) when :ex seq = [] From 5d3da0389376e3f8b2f801316c3ef754852ee0ed Mon Sep 17 00:00:00 2001 From: Shaun Mangelsdorf Date: Fri, 4 Apr 2014 16:50:17 +1000 Subject: [PATCH 035/435] Time out test case when reading from a pipe blocks indefinitely --- spec/integration/ssl_ber_spec.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/integration/ssl_ber_spec.rb b/spec/integration/ssl_ber_spec.rb index 4f40a204..ae8900e3 100644 --- a/spec/integration/ssl_ber_spec.rb +++ b/spec/integration/ssl_ber_spec.rb @@ -1,15 +1,18 @@ require 'spec_helper' require 'net/ldap' +require 'timeout' describe "BER serialisation (SSL)" do # Transmits str to #to and reads it back from #from. # def transmit(str) - to.write(str) - to.close - - from.read + Timeout::timeout(1) do + to.write(str) + to.close + + from.read + end end attr_reader :to, :from From 0c439a94a2e67136f43a16fba34695120997b49e Mon Sep 17 00:00:00 2001 From: Shaun Mangelsdorf Date: Fri, 4 Apr 2014 16:56:40 +1000 Subject: [PATCH 036/435] Add raw_string helper in tests, to repair encoding issues Strings with raw byte sequences misbehave in Ruby 2.0+ because the default encoding for string literals is now UTF-8. The String#b method resolves this, and was not previously available. --- spec/spec_helper.rb | 5 ++++ spec/unit/ber/ber_spec.rb | 42 +++++++++++++-------------- spec/unit/ber/core_ext/string_spec.rb | 4 +-- spec/unit/ldap/filter_spec.rb | 4 +-- test/test_snmp.rb | 11 +++++-- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 50795370..a5853980 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,4 +2,9 @@ RSpec.configure do |config| config.mock_with :flexmock + + def raw_string(s) + # Conveniently, String#b only needs to be called when it exists + s.respond_to?(:b) ? s.b : s + end end diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 48e161ad..9806cc85 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -33,28 +33,28 @@ context "numbers" do # Sample based { - 0 => "\x02\x01\x00", - 1 => "\x02\x01\x01", - 127 => "\x02\x01\x7F", - 128 => "\x02\x01\x80", - 255 => "\x02\x01\xFF", - 256 => "\x02\x02\x01\x00", - 65535 => "\x02\x02\xFF\xFF", - 65536 => "\x02\x03\x01\x00\x00", - 16_777_215 => "\x02\x03\xFF\xFF\xFF", - 0x01000000 => "\x02\x04\x01\x00\x00\x00", - 0x3FFFFFFF => "\x02\x04\x3F\xFF\xFF\xFF", - 0x4FFFFFFF => "\x02\x04\x4F\xFF\xFF\xFF", - + 0 => raw_string("\x02\x01\x00"), + 1 => raw_string("\x02\x01\x01"), + 127 => raw_string("\x02\x01\x7F"), + 128 => raw_string("\x02\x01\x80"), + 255 => raw_string("\x02\x01\xFF"), + 256 => raw_string("\x02\x02\x01\x00"), + 65535 => raw_string("\x02\x02\xFF\xFF"), + 65536 => raw_string("\x02\x03\x01\x00\x00"), + 16_777_215 => raw_string("\x02\x03\xFF\xFF\xFF"), + 0x01000000 => raw_string("\x02\x04\x01\x00\x00\x00"), + 0x3FFFFFFF => raw_string("\x02\x04\x3F\xFF\xFF\xFF"), + 0x4FFFFFFF => raw_string("\x02\x04\x4F\xFF\xFF\xFF"), + # Some odd samples... - 5 => "\002\001\005", - 500 => "\002\002\001\364", - 50_000 => "\x02\x02\xC3P", - 5_000_000_000 => "\002\005\001*\005\362\000" - }.each do |number, expected_encoding| + 5 => raw_string("\002\001\005"), + 500 => raw_string("\002\002\001\364"), + 50_000 => raw_string("\x02\x02\xC3P"), + 5_000_000_000 => raw_string("\002\005\001*\005\362\000") + }.each do |number, expected_encoding| it "should encode #{number} as #{expected_encoding.inspect}" do number.to_ber.should == expected_encoding - end + end end # Round-trip encoding: This is mostly to be sure to cover Bignums well. @@ -79,7 +79,7 @@ context "strings" do it "should properly encode UTF-8 strings" do "\u00e5".force_encoding("UTF-8").to_ber.should == - "\x04\x02\xC3\xA5" + raw_string("\x04\x02\xC3\xA5") end it "should properly encode strings encodable as UTF-8" do "teststring".encode("US-ASCII").to_ber.should == "\x04\nteststring" @@ -87,7 +87,7 @@ it "should properly encode binary data strings using to_ber_bin" do # This is used for searching for GUIDs in Active Directory ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == - "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16" + raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") end it "should not fail on strings that can not be converted to UTF-8" do error = Encoding::UndefinedConversionError diff --git a/spec/unit/ber/core_ext/string_spec.rb b/spec/unit/ber/core_ext/string_spec.rb index 6eebe05c..ef2c4981 100644 --- a/spec/unit/ber/core_ext/string_spec.rb +++ b/spec/unit/ber/core_ext/string_spec.rb @@ -6,7 +6,7 @@ context "when passed an ldap bind request and some extra data" do attr_reader :str, :result before(:each) do - @str = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED" + @str = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED") @result = str.read_ber!(Net::LDAP::AsnSyntax) end @@ -22,7 +22,7 @@ before(:each) do stub_exception_class = Class.new(StandardError) - @initial_value = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" + @initial_value = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus") @str = initial_value.dup # Defines a string diff --git a/spec/unit/ldap/filter_spec.rb b/spec/unit/ldap/filter_spec.rb index 5e4cb8a8..06fd3b80 100644 --- a/spec/unit/ldap/filter_spec.rb +++ b/spec/unit/ldap/filter_spec.rb @@ -83,12 +83,12 @@ def eq(attribute, value) end context 'with a well-known BER string' do - ber = "\xa4\x2d" \ + ber = raw_string("\xa4\x2d" \ "\x04\x0b" "objectclass" \ "\x30\x1e" \ "\x80\x08" "foo" "*\\" "bar" \ "\x81\x08" "foo" "*\\" "bar" \ - "\x82\x08" "foo" "*\\" "bar" + "\x82\x08" "foo" "*\\" "bar") describe "<- .to_ber" do [ diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 88a619dc..065025ed 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -4,10 +4,15 @@ require 'net/snmp' class TestSnmp < Test::Unit::TestCase - SnmpGetRequest = "0'\002\001\000\004\006public\240\032\002\002?*\002\001\000\002\001\0000\0160\f\006\b+\006\001\002\001\001\001\000\005\000" - SnmpGetResponse = "0+\002\001\000\004\006public\242\036\002\002'\017\002\001\000\002\001\0000\0220\020\006\b+\006\001\002\001\001\001\000\004\004test" + def self.raw_string(s) + # Conveniently, String#b only needs to be called when it exists + s.respond_to?(:b) ? s.b : s + end + + SnmpGetRequest = raw_string("0'\002\001\000\004\006public\240\032\002\002?*\002\001\000\002\001\0000\0160\f\006\b+\006\001\002\001\001\001\000\005\000") + SnmpGetResponse = raw_string("0+\002\001\000\004\006public\242\036\002\002'\017\002\001\000\002\001\0000\0220\020\006\b+\006\001\002\001\001\001\000\004\004test") - SnmpGetRequestXXX = "0'\002\001\000\004\006xxxxxx\240\032\002\002?*\002\001\000\002\001\0000\0160\f\006\b+\006\001\002\001\001\001\000\005\000" + SnmpGetRequestXXX = raw_string("0'\002\001\000\004\006xxxxxx\240\032\002\002?*\002\001\000\002\001\0000\0160\f\006\b+\006\001\002\001\001\001\000\005\000") def test_invalid_packet data = "xxxx" From 839c50fdd6cc797a8944848bc46752d51a142a8c Mon Sep 17 00:00:00 2001 From: Shaun Mangelsdorf Date: Sat, 5 Apr 2014 15:48:12 +1000 Subject: [PATCH 037/435] Work around broken sync_close in OpenSSL::SSL::SSLSocket ssl_ber_spec showed failures on Ruby 1.9.3, 2.0.0 and 2.1.1 (OS X and Linux) which could only be resolved by manually closing the underlying connection. Changing the test to use a TCP socket did not help, so it seems to be a bug in the SSLSocket class. --- lib/net/ldap.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index be21c1ef..95eb2811 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1160,14 +1160,24 @@ def getbyte end end + module FixSSLSocketSyncClose + def close + super + io.close + end + end + def self.wrap_with_ssl(io) raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new conn = OpenSSL::SSL::SSLSocket.new(io, ctx) conn.connect - conn.sync_close = true + + # Doesn't work: + # conn.sync_close = true conn.extend(GetbyteForSSLSocket) unless conn.respond_to?(:getbyte) + conn.extend(FixSSLSocketSyncClose) conn end From f765a75fd07f37363a4c9b80f5bb828956746f5f Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Mon, 7 Apr 2014 12:04:35 +0200 Subject: [PATCH 038/435] push version to 0.6.0 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 1c5566e6..f2b1fb33 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.5.1" + VERSION = "0.6.0" end end From d4a73558ef847d6e0e19f5697f3e1003d1758d15 Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Mon, 14 Apr 2014 09:19:27 +0200 Subject: [PATCH 039/435] fix url of github in gemspec file, push version to 0.6.1 #85 --- lib/net/ldap/version.rb | 2 +- net-ldap.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index f2b1fb33..9aa80d6b 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.6.0" + VERSION = "0.6.1" end end diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 01545adf..cfac6ccd 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -25,7 +25,7 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] - s.homepage = %q{http://github.com.org/ruby-ldap/ruby-net-ldap} + s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] s.required_ruby_version = Gem::Requirement.new(">= 1.8.7") From bc45065c89bb3cd51cd35e52d9075e60da65771b Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Thu, 1 Aug 2013 17:05:08 +0900 Subject: [PATCH 040/435] FilterParser can parse filter string including special chars. --- lib/net/ldap/filter.rb | 2 +- spec/unit/ldap/filter_parser_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 66610010..01e3d49f 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -755,7 +755,7 @@ def parse_filter_branch(scanner) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) - if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) + if value = scanner.scan(/(?:[-\[\]{}\w*.+@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) # 20100313 AZ: Assumes that "(uid=george*)" is the same as # "(uid=george* )". The standard doesn't specify, but I can find # no examples that suggest otherwise. diff --git a/spec/unit/ldap/filter_parser_spec.rb b/spec/unit/ldap/filter_parser_spec.rb index e34828eb..434743ac 100644 --- a/spec/unit/ldap/filter_parser_spec.rb +++ b/spec/unit/ldap/filter_parser_spec.rb @@ -6,12 +6,23 @@ describe "#parse" do context "Given ASCIIs as filter string" do let(:filter_string) { "(cn=name)" } + specify "should generate filter object" do expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter end end + context "Given string including multibyte chars as filter string" do let(:filter_string) { "(cn=名前)" } + + specify "should generate filter object" do + expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter + end + end + + context 'Given string including special chars allowd to be used in DN as filter string' do + let(:filter_string) { '(cn=[{^something~}])' } + specify "should generate filter object" do expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter end From 01015aafcbee89361c2ea58f5a3318725a4f5998 Mon Sep 17 00:00:00 2001 From: sdalu Date: Wed, 14 May 2014 19:16:02 +0200 Subject: [PATCH 041/435] Adding Net::LDAP::Entry#first --- lib/net/ldap/entry.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index 616ffe7f..9ab4bb6d 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -113,6 +113,14 @@ def [](name) @myhash[name] || [] end + ## + # Read the first value for the provided attribute. The attribute name + # is canonicalized prior to reading. Returns nil if the attribute does + # not exist. + def first(name) + self[name].first + end + ## # Returns the first distinguished name (dn) of the Entry as a \String. def dn From cd792ad91d2d238ce8fac5b56c833df84697571f Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Fri, 23 May 2014 22:30:52 +0300 Subject: [PATCH 042/435] Manually merged in changes from https://github.com/ruby-ldap/ruby-net-ldap/pull/88, so we have a working version. --- lib/net/ber/core_ext/string.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/net/ber/core_ext/string.rb b/lib/net/ber/core_ext/string.rb index a0fcfb46..b4ad8039 100644 --- a/lib/net/ber/core_ext/string.rb +++ b/lib/net/ber/core_ext/string.rb @@ -33,7 +33,9 @@ def raw_utf8_encoded rescue Encoding::UndefinedConversionError self rescue Encoding::ConverterNotFoundError - return self + self + rescue Encoding::InvalidByteSequenceError + self end else self From 64c96ea0472687158dfa5df50ea6e8631f620302 Mon Sep 17 00:00:00 2001 From: Brian John Date: Mon, 16 Jun 2014 13:00:42 -0500 Subject: [PATCH 043/435] Remove references to rubyforge Remove references to rubyforge since it has been shut down (see https://twitter.com/evanphx/status/399552820380053505) --- README.rdoc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.rdoc b/README.rdoc index 32c9f6e9..affb1422 100644 --- a/README.rdoc +++ b/README.rdoc @@ -16,13 +16,8 @@ the most recent LDAP RFCs (4510–4519, plus portions of 4520–4532). == Where -* {RubyForge}[http://rubyforge.org/projects/net-ldap] * {GitHub}[https://github.com/ruby-ldap/ruby-net-ldap] * {ruby-ldap@googlegroups.com}[http://groups.google.com/group/ruby-ldap] -* {Documentation}[http://net-ldap.rubyforge.org/] - -The Net::LDAP for Ruby documentation, project description, and main downloads -can currently be found on {RubyForge}[http://rubyforge.org/projects/net-ldap]. == Synopsis From dc3de1e137e0c452d6c49d15eafc38693fe8761c Mon Sep 17 00:00:00 2001 From: Sai Ke WANG Date: Tue, 8 Jul 2014 14:03:51 -0400 Subject: [PATCH 044/435] Fix net-ldap with start-tls. Something along the line of http://stackoverflow.com/questions/18453894/confused-about-ber-basic-encoding-rules From the unpatched gem, the following LDAP "extended request" with (1.3.6.1.4.1.1466.20037 LDAP_START_TLS_OID" is sent: ======== 0000 fa 16 3e 91 ff 71 fa 16 3e 43 45 a0 08 00 45 00 ..>..q..>CE...E. 0010 00 53 e8 52 40 00 40 06 94 ab 01 7d 0c 85 ac 11 .S.R@.@....}.... 0020 03 94 85 87 01 85 41 b9 73 45 3f 17 c3 ba 80 18 ......A.sE?..... 0030 01 c9 bd ec 00 00 01 01 08 0a 70 dc 9b 15 17 6b ..........p....k 0040 1a e8 30 1d 02 01 01 77 18 04 16 31 2e 33 2e 36 ..0....w...1.3.6 0050 2e 31 2e 34 2e 31 2e 31 34 36 36 2e 32 30 30 33 .1.4.1.1466.2003 0060 37 7 ======== but the server would reset the connection and wireshark indicate the '04' byte is invalid. With ApacheDS, the request looks like the following: ======== 0000 fa 16 3e 91 ff 71 fa 16 3e 43 45 a0 08 00 45 00 ..>..q..>CE...E. 0010 00 53 60 a8 40 00 40 06 3c bc 01 7d 0c 85 0a 7a .S`.@.@.<..}...z 0020 84 c5 9d 9f 01 85 ad cb b4 99 bd ae b2 ef 80 18 ................ 0030 01 c9 9d 86 00 00 01 01 08 0a 70 dc d4 40 17 6b ..........p..@.k 0040 64 4c 30 1d 02 01 01 77 18 80 16 31 2e 33 2e 36 dL0....w...1.3.6 0050 2e 31 2e 34 2e 31 2e 31 34 36 36 2e 32 30 30 33 .1.4.1.1466.2003 0060 37 7 ======== This patch makes the request the same as ApacheDS' and worked fine. --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index be21c1ef..76636691 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1206,7 +1206,7 @@ def setup_encryption(args) # go here. when :start_tls msgid = next_msgid.to_ber - request = [Net::LDAP::StartTlsOid.to_ber].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) request_pkt = [msgid, request].to_ber_sequence @conn.write request_pkt be = @conn.read_ber(Net::LDAP::AsnSyntax) From 38716a2bfbf8faaab1f3a5f4ae9668e560649753 Mon Sep 17 00:00:00 2001 From: "Nicholas E. Rabenau" Date: Thu, 31 Jul 2014 22:41:22 +0200 Subject: [PATCH 045/435] Update respond_to? for Ruby 2.0 Marshal.dump will choke on the attempt to serialize an LDAP::Entry. This change fixes that by updating the signature of respond_to? to Ruby 2.0 level. --- lib/net/ldap/entry.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index 616ffe7f..6a157615 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -147,7 +147,7 @@ def to_ldif Net::LDAP::Dataset.from_entry(self).to_ldif_string end - def respond_to?(sym) #:nodoc: + def respond_to?(sym, include_all = false) #:nodoc: return true if valid_attribute?(self.class.attribute_name(sym)) return super end From 02804d7c18050d7397beaa7c43d65b56bbf30521 Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Mon, 4 Aug 2014 18:09:20 +0200 Subject: [PATCH 046/435] push version to 0.7.0 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 9aa80d6b..36334574 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.6.1" + VERSION = "0.7.0" end end From c0f6e130fe43645e1206825d1bb418a6e8a5b171 Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Thu, 7 Aug 2014 09:12:19 +1000 Subject: [PATCH 047/435] RubyForge is gone Remove references to RubyForge, as the project is defunct. Point to the http://rubydoc.info/gems/net-ldap docs instead. --- Hacking.rdoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Hacking.rdoc b/Hacking.rdoc index 09452514..1db37cb2 100644 --- a/Hacking.rdoc +++ b/Hacking.rdoc @@ -25,7 +25,7 @@ patches being accepted, we recommend that you follow the guidelines below: == Documentation -* Documentation: {net-ldap}[http://net-ldap.rubyforge.org/] +* Documentation: {net-ldap}[http://rubydoc.info/gems/net-ldap] It is very important that, if you add new methods or objects, your code is well-documented. The purpose of the changes should be clearly described so that @@ -63,6 +63,5 @@ installed using RubyGems. == Participation -* RubyForge: {net-ldap}[http://rubyforge.org/projects/net-ldap] * GitHub: {ruby-ldap/ruby-net-ldap}[https://github.com/ruby-ldap/ruby-net-ldap/] * Group: {ruby-ldap}[http://groups.google.com/group/ruby-ldap] From 97cbb4c14aefc4b49b682301b8c828c05e2c9a72 Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Thu, 7 Aug 2014 09:16:13 +1000 Subject: [PATCH 048/435] Report bugs on GitHub There seems to be issues open on GitHub, so I gambled that's the official source now that RubyForge is gone. --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 3c872a4d..948fddaa 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -858,7 +858,7 @@ def add(args) # The LDAP protocol provides a full and well thought-out set of operations # for changing the values of attributes, but they are necessarily somewhat # complex and not always intuitive. If these instructions are confusing or - # incomplete, please send us email or create a bug report on rubyforge. + # incomplete, please send us email or create an issue on GitHub. # # The :operations parameter to #modify takes an array of # operation-descriptors. Each individual operation is specified in one From e559d8fa5ccc1a98d5c581ed0651c3a006974fbe Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 15:28:36 -0700 Subject: [PATCH 049/435] Extract wire write/read calls This will make it easier to add instrumentation hooks. It also reduces the amount of duplication (for read, specifically). --- lib/net/ldap.rb | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 948fddaa..8ab5b3f0 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1218,8 +1218,8 @@ def setup_encryption(args) msgid = next_msgid.to_ber request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) request_pkt = [msgid, request].to_ber_sequence - @conn.write request_pkt - be = @conn.read_ber(Net::LDAP::AsnSyntax) + write request_pkt + be = read raise Net::LDAP::LdapError, "no start_tls result" if be.nil? pdu = Net::LDAP::PDU.new(be) raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? @@ -1243,6 +1243,16 @@ def close @conn = nil end + def read + @conn.read_ber(Net::LDAP::AsnSyntax) + end + private :read + + def write(packet) + @conn.write(packet) + end + private :write + def next_msgid @msgid ||= 0 @msgid += 1 @@ -1278,9 +1288,9 @@ def bind_simple(auth) request = [LdapVersion.to_ber, user.to_ber, psw.to_ber_contextspecific(0)].to_ber_appsequence(0) request_pkt = [msgid, request].to_ber_sequence - @conn.write request_pkt + write request_pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" pdu end @@ -1317,9 +1327,9 @@ def bind_sasl(auth) sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) request_pkt = [msgid, request].to_ber_sequence - @conn.write request_pkt + write request_pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" return pdu unless pdu.result_code == 14 # saslBindInProgress raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) @@ -1483,12 +1493,12 @@ def search(args = {}) controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - @conn.write pkt + write pkt result_pdu = nil controls = [] - while (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) + while (be = read) && (pdu = Net::LDAP::PDU.new(be)) case pdu.app_tag when 4 # search-data n_results += 1 @@ -1584,9 +1594,9 @@ def modify(args) request = [ modify_dn.to_ber, ops.to_ber_sequence ].to_ber_appsequence(6) pkt = [ next_msgid.to_ber, request ].to_ber_sequence - @conn.write pkt + write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end @@ -1607,9 +1617,9 @@ def add(args) request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8) pkt = [next_msgid.to_ber, request].to_ber_sequence - @conn.write pkt + write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 9) or raise Net::LDAP::LdapError, "response missing or invalid" @@ -1630,9 +1640,9 @@ def rename(args) request << new_superior.to_ber_contextspecific(0) unless new_superior == nil pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence - @conn.write pkt + write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && + (be = read) && (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == 13) or raise Net::LDAP::LdapError.new( "response missing or invalid" ) @@ -1647,9 +1657,9 @@ def delete(args) 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(10) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - @conn.write pkt + write pkt - (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end From 9ad1876527ab89a70603e79c878f2cea902d0279 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 15:39:27 -0700 Subject: [PATCH 050/435] Accept syntax param for read --- lib/net/ldap.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 8ab5b3f0..58b060fb 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1243,8 +1243,8 @@ def close @conn = nil end - def read - @conn.read_ber(Net::LDAP::AsnSyntax) + def read(syntax = Net::LDAP::AsnSyntax) + @conn.read_ber(syntax) end private :read From 87d28e95ef6d8059df7ad4d6c2ddca21da8e6c5e Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 16:22:25 -0700 Subject: [PATCH 051/435] Implement network read/write instrumentation --- lib/net/ldap.rb | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 58b060fb..f9198ab2 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1139,6 +1139,8 @@ class Net::LDAP::Connection #:nodoc: MaxSaslChallenges = 10 def initialize(server) + @instrumentation_service = server[:instrumentation_service] + begin @conn = TCPSocket.new(server[:host], server[:port]) rescue SocketError @@ -1233,6 +1235,21 @@ def setup_encryption(args) end end + # Internal: Instrument a block with the defined instrumentation service. + # + # Returns the return value of the block. + def instrument(event, payload = {}) + return yield unless instrumentation_service + + instrumentation_service.instrument(event, payload) do + yield + end + end + private :instrument + + attr_reader :instrumentation_service + private :instrumentation_service + #-- # This is provided as a convenience method to make sure a connection # object gets closed without waiting for a GC to happen. Clients shouldn't @@ -1244,12 +1261,16 @@ def close end def read(syntax = Net::LDAP::AsnSyntax) - @conn.read_ber(syntax) + instrument "read.net_ldap_connection", :syntax => syntax do + @conn.read_ber(syntax) + end end private :read def write(packet) - @conn.write(packet) + instrument "write.net_ldap_connection", :packet => packet do + @conn.write(packet) + end end private :write From 3eefb84819dd0df8d315e0baf8f5032fcd451d87 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 16:22:37 -0700 Subject: [PATCH 052/435] Spec out read/write instrumentation --- spec/unit/ldap_spec.rb | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 272d4eee..98b98e3f 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -75,4 +75,53 @@ result.error_message.should == "" end end + + context "instrumentation" do + class InstrumentationService + attr_reader :events + + def initialize + @events = [] + end + + def instrument(event, payload) + result = yield + @events << [event, payload, result] + result + end + end + + before do + @tcp_socket = flexmock(:connection) + @tcp_socket.should_receive(:write) + flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + @service = InstrumentationService.new + end + + subject do + Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636, + :instrumentation_service => @service) + end + + it "should publish a socket write event, followed by a socket read event" do + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = 7 + result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(result) + + result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) + result.should be_success + + # a write event, then a read event + @service.events.size.should == 2 + + event, payload, result = @service.events.shift + event.should == "write.net_ldap_connection" + payload.should have_key(:packet) + + event, payload, result = @service.events.shift + event.should == "read.net_ldap_connection" + result.should == result + end + end end From 97e035a9798678ab36e496b505473cb95ef0d702 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 16:35:03 -0700 Subject: [PATCH 053/435] Wire up instrumentation_service settings Configure it on Net::LDAP instance and it will be passed to the Net::LDAP::Connection object. --- lib/net/ldap.rb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index f9198ab2..791d0eba 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -400,6 +400,8 @@ def initialize(args = {}) @auth[:password] = pr.call end + @instrumentation_service = args[:instrumentation_service] + # This variable is only set when we are created with LDAP::open. All of # our internal methods will connect using it, or else they will create # their own. @@ -572,10 +574,12 @@ def open raise Net::LDAP::LdapError, "Open already in progress" if @open_connection begin - @open_connection = Net::LDAP::Connection.new(:host => @host, - :port => @port, - :encryption => - @encryption) + @open_connection = + Net::LDAP::Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service @open_connection.bind(@auth) yield self ensure @@ -730,8 +734,11 @@ def bind(auth = @auth) @result = @open_connection.bind(auth) else begin - conn = Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service @result = conn.bind(auth) ensure conn.close if conn From d2df85e0b7c600f600ccaab9ecf2ac587c05d1bb Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 16:35:27 -0700 Subject: [PATCH 054/435] Spec out Net::LDAP instrumentation service settings --- spec/spec_helper.rb | 14 +++++++++++++ spec/unit/ldap_spec.rb | 46 ++++++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a5853980..404c96da 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,3 +8,17 @@ def raw_string(s) s.respond_to?(:b) ? s.b : s end end + +class MockInstrumentationService + attr_reader :events + + def initialize + @events = [] + end + + def instrument(event, payload) + result = yield + @events << [event, payload, result] + result + end +end diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 98b98e3f..62aa55c3 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -1,5 +1,35 @@ require 'spec_helper' +describe Net::LDAP do + describe "initialize" do + context "on instrumentation_service configuration" do + before do + @tcp_socket = flexmock(:connection) + @tcp_socket.should_receive(:close) + flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + @service = MockInstrumentationService.new + end + + it "should set the service object and instrument network calls" do + ldap = Net::LDAP.new(:server => 'test.mocked.com', :port => 636, + :instrumentation_service => @service) + + @tcp_socket.should_receive(:write) + + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = 7 + result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(result) + + ldap.bind.should be_true + + # a write event, then a read event + @service.events.size.should == 2 + end + end + end +end + describe Net::LDAP::Connection do describe "initialize" do context "when host is not responding" do @@ -77,25 +107,11 @@ end context "instrumentation" do - class InstrumentationService - attr_reader :events - - def initialize - @events = [] - end - - def instrument(event, payload) - result = yield - @events << [event, payload, result] - result - end - end - before do @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) - @service = InstrumentationService.new + @service = MockInstrumentationService.new end subject do From 508a5533b44093fe4385ba05b7f44daa44e4a330 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 20:59:21 -0700 Subject: [PATCH 055/435] Record result in payload, pass payload to block --- lib/net/ldap.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 791d0eba..234a0a38 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1246,10 +1246,10 @@ def setup_encryption(args) # # Returns the return value of the block. def instrument(event, payload = {}) - return yield unless instrumentation_service + return yield(payload) unless instrumentation_service - instrumentation_service.instrument(event, payload) do - yield + instrumentation_service.instrument(event, payload) do |payload| + payload[:result] = yield(payload) end end private :instrument From 4884bff2824a39cbb501a2159a81aedf6413e829 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 21:48:46 -0700 Subject: [PATCH 056/435] Yield payload in mock service Replicates the ActiveSupport::Notifications behavior. --- spec/spec_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 404c96da..72451ae4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -17,7 +17,7 @@ def initialize end def instrument(event, payload) - result = yield + result = yield(payload) @events << [event, payload, result] result end From e1aa7597c0beb08a5217c6e648a60bf2f8d0f1ee Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 22:16:07 -0700 Subject: [PATCH 057/435] Instrument content length from read_ber --- lib/net/ber/ber_parser.rb | 1 + lib/net/ldap.rb | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/net/ber/ber_parser.rb b/lib/net/ber/ber_parser.rb index 682a5999..47379b87 100644 --- a/lib/net/ber/ber_parser.rb +++ b/lib/net/ber/ber_parser.rb @@ -160,6 +160,7 @@ def read_ber(syntax = nil) if -1 == content_length raise Net::BER::BerError, "Indeterminite BER content length not implemented." else + yield id, content_length if block_given? data = read(content_length) end diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 234a0a38..124ccb11 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1268,8 +1268,11 @@ def close end def read(syntax = Net::LDAP::AsnSyntax) - instrument "read.net_ldap_connection", :syntax => syntax do - @conn.read_ber(syntax) + instrument "read.net_ldap_connection", :syntax => syntax do |payload| + @conn.read_ber(syntax) do |id, content_length| + payload[:response_id] = id + payload[:content_length] = content_length + end end end private :read From c6730f7ab8feb6c255948969e26108d0868ffb64 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 24 Aug 2014 22:16:38 -0700 Subject: [PATCH 058/435] Fix logic error in tests --- spec/unit/ldap_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 62aa55c3..1037aa4e 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -122,8 +122,8 @@ it "should publish a socket write event, followed by a socket read event" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) ber.ber_identifier = 7 - result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(result) + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) result.should be_success @@ -133,11 +133,13 @@ event, payload, result = @service.events.shift event.should == "write.net_ldap_connection" + payload.should have_key(:result) payload.should have_key(:packet) event, payload, result = @service.events.shift event.should == "read.net_ldap_connection" - result.should == result + payload.should have_key(:result) + result.should == read_result end end end From 6790cea590f773e754dc4159f0dc088c6b41fb88 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 25 Aug 2014 15:03:09 -0700 Subject: [PATCH 059/435] Construct Connection with instrumentation service in search --- lib/net/ldap.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 124ccb11..260fbda4 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -652,8 +652,11 @@ def search(args = {}) } else begin - conn = Net::LDAP::Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Net::LDAP::Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.search(args) { |entry| result_set << entry if result_set From ba4dfc222e191920648b15158cf521ef2adbeb65 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 25 Aug 2014 15:06:53 -0700 Subject: [PATCH 060/435] Bump to current + 1 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 9aa80d6b..c5e843f9 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.6.1" + VERSION = "0.7.1" end end From b6eb872172bea1f1369d048cbea7181651386658 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 25 Aug 2014 23:20:31 -0700 Subject: [PATCH 061/435] Revert "Bump to current + 1" This reverts commit ba4dfc222e191920648b15158cf521ef2adbeb65. --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index c5e843f9..9aa80d6b 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.7.1" + VERSION = "0.6.1" end end From 12ae55bc380537ea3c6b59257723aa5af5386e05 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 00:45:53 -0700 Subject: [PATCH 062/435] Add service#subscribe to listen for specific events --- spec/spec_helper.rb | 12 ++++++++---- spec/unit/ldap_spec.rb | 32 ++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 72451ae4..820dac30 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,15 +10,19 @@ def raw_string(s) end class MockInstrumentationService - attr_reader :events - def initialize - @events = [] + @events = {} end def instrument(event, payload) result = yield(payload) - @events << [event, payload, result] + @events[event] ||= [] + @events[event] << [payload, result] result end + + def subscribe(event) + @events[event] ||= [] + @events[event] + end end diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 1037aa4e..dc4c1a71 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -14,17 +14,25 @@ ldap = Net::LDAP.new(:server => 'test.mocked.com', :port => 636, :instrumentation_service => @service) - @tcp_socket.should_receive(:write) + @tcp_socket.should_receive(:write).and_return(bytes_written = 1) + + write_events = @service.subscribe "write.net_ldap_connection" + read_events = @service.subscribe "read.net_ldap_connection" ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) ber.ber_identifier = 7 - result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(result) + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) ldap.bind.should be_true - # a write event, then a read event - @service.events.size.should == 2 + # a write event + payload, result = write_events.pop + result.should == bytes_written + + # then a read event + payload, result = read_events.pop + result.should == read_result end end end @@ -125,19 +133,19 @@ read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) + write_events = @service.subscribe "write.net_ldap_connection" + read_events = @service.subscribe "read.net_ldap_connection" + result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) result.should be_success - # a write event, then a read event - @service.events.size.should == 2 - - event, payload, result = @service.events.shift - event.should == "write.net_ldap_connection" + # a write event + payload, result = write_events.pop payload.should have_key(:result) payload.should have_key(:packet) - event, payload, result = @service.events.shift - event.should == "read.net_ldap_connection" + # then a read event + payload, result = read_events.pop payload.should have_key(:result) result.should == read_result end From 443502203126335fb2c2a812eb8d9d40c32abfd9 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 00:46:15 -0700 Subject: [PATCH 063/435] Instrument Net::LDAP::Connection#search --- lib/net/ldap.rb | 196 ++++++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 90 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 260fbda4..686767ca 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1488,108 +1488,124 @@ def search(args = {}) result_pdu = nil n_results = 0 - loop { - # should collect this into a private helper to clarify the structure - query_limit = 0 - if sizelimit > 0 - if paged_searches_supported - query_limit = (((sizelimit - n_results) < 126) ? (sizelimit - - n_results) : 0) - else - query_limit = sizelimit + instrument "search.net_ldap_connection", + :filter => search_filter, + :base => search_base, + :scope => scope, + :limit => sizelimit, + :sort => sort_control, + :referrals => return_referrals, + :deref => deref, + :attributes => search_attributes do |payload| + loop do + # should collect this into a private helper to clarify the structure + query_limit = 0 + if sizelimit > 0 + if paged_searches_supported + query_limit = (((sizelimit - n_results) < 126) ? (sizelimit - + n_results) : 0) + else + query_limit = sizelimit + end end - end - request = [ - search_base.to_ber, - scope.to_ber_enumerated, - deref.to_ber_enumerated, - query_limit.to_ber, # size limit - 0.to_ber, - attributes_only.to_ber, - search_filter.to_ber, - search_attributes.to_ber_sequence - ].to_ber_appsequence(3) - - # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory - # this breaks when calling to_ber. (Can't force binary data to UTF-8) - # we have to disable paging (even though server supports it) to get around this... - - controls = [] - controls << - [ - Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber, - # Criticality MUST be false to interoperate with normal LDAPs. - false.to_ber, - rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber - ].to_ber_sequence if paged_searches_supported - controls << sort_control if sort_control - controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) - - pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - write pkt - - result_pdu = nil - controls = [] - - while (be = read) && (pdu = Net::LDAP::PDU.new(be)) - case pdu.app_tag - when 4 # search-data - n_results += 1 - yield pdu.search_entry if block_given? - when 19 # search-referral - if return_referrals - if block_given? - se = Net::LDAP::Entry.new - se[:search_referrals] = (pdu.search_referrals || []) - yield se + request = [ + search_base.to_ber, + scope.to_ber_enumerated, + deref.to_ber_enumerated, + query_limit.to_ber, # size limit + 0.to_ber, + attributes_only.to_ber, + search_filter.to_ber, + search_attributes.to_ber_sequence + ].to_ber_appsequence(3) + + # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory + # this breaks when calling to_ber. (Can't force binary data to UTF-8) + # we have to disable paging (even though server supports it) to get around this... + + controls = [] + controls << + [ + Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber, + # Criticality MUST be false to interoperate with normal LDAPs. + false.to_ber, + rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber + ].to_ber_sequence if paged_searches_supported + controls << sort_control if sort_control + controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) + + pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence + write pkt + + result_pdu = nil + controls = [] + + while (be = read) && (pdu = Net::LDAP::PDU.new(be)) + case pdu.app_tag + when 4 # search-data + n_results += 1 + yield pdu.search_entry if block_given? + when 19 # search-referral + if return_referrals + if block_given? + se = Net::LDAP::Entry.new + se[:search_referrals] = (pdu.search_referrals || []) + yield se + end end - end - when 5 # search-result - result_pdu = pdu - controls = pdu.result_controls - if return_referrals && pdu.result_code == 10 - if block_given? - se = Net::LDAP::Entry.new - se[:search_referrals] = (pdu.search_referrals || []) - yield se + when 5 # search-result + result_pdu = pdu + controls = pdu.result_controls + if return_referrals && pdu.result_code == 10 + if block_given? + se = Net::LDAP::Entry.new + se[:search_referrals] = (pdu.search_referrals || []) + yield se + end end + break + else + raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" end - break - else - raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" end - end - # When we get here, we have seen a type-5 response. If there is no - # error AND there is an RFC-2696 cookie, then query again for the next - # page of results. If not, we're done. Don't screw this up or we'll - # break every search we do. - # - # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't - # that have a parameter of AsnSyntax? Does this just accidentally - # work? According to RFC-2696, the value expected in this position is - # of type OCTET STRING, covered in the default syntax supported by - # read_ber, so I guess we're ok. - more_pages = false - if result_pdu.result_code == 0 and controls - controls.each do |c| - if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS - # just in case some bogus server sends us more than 1 of these. - more_pages = false - if c.value and c.value.length > 0 - cookie = c.value.read_ber[1] - if cookie and cookie.length > 0 - rfc2696_cookie[1] = cookie - more_pages = true + # count number of pages of results + payload[:page_count] ||= 0 + payload[:page_count] += 1 + + # When we get here, we have seen a type-5 response. If there is no + # error AND there is an RFC-2696 cookie, then query again for the next + # page of results. If not, we're done. Don't screw this up or we'll + # break every search we do. + # + # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't + # that have a parameter of AsnSyntax? Does this just accidentally + # work? According to RFC-2696, the value expected in this position is + # of type OCTET STRING, covered in the default syntax supported by + # read_ber, so I guess we're ok. + more_pages = false + if result_pdu.result_code == 0 and controls + controls.each do |c| + if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS + # just in case some bogus server sends us more than 1 of these. + more_pages = false + if c.value and c.value.length > 0 + cookie = c.value.read_ber[1] + if cookie and cookie.length > 0 + rfc2696_cookie[1] = cookie + more_pages = true + end end end end end - end - break unless more_pages - } # loop + break unless more_pages + end # loop + + payload[:result_count] = n_results + end # instrument result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") end From ffed4f02ac0839a67aa1914c11ec83ba026fdc63 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 01:08:50 -0700 Subject: [PATCH 064/435] Extract instrumentation for reuse Allows us to use the same method for Net::LDAP and Net::LDAP::Connection. --- lib/net/ldap.rb | 19 ++++--------------- lib/net/ldap/instrumentation.rb | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 lib/net/ldap/instrumentation.rb diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 686767ca..76175ea6 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -23,6 +23,7 @@ class LDAP require 'net/ldap/dataset' require 'net/ldap/password' require 'net/ldap/entry' +require 'net/ldap/instrumentation' require 'net/ldap/version' # == Quick-start for the Impatient @@ -242,6 +243,7 @@ class LDAP # and then keeps it open while it executes a user-supplied block. # Net::LDAP#open closes the connection on completion of the block. class Net::LDAP + include Net::LDAP::Instrumentation class LdapError < StandardError; end @@ -1145,6 +1147,8 @@ def paged_searches_supported? # This is a private class used internally by the library. It should not # be called by user code. class Net::LDAP::Connection #:nodoc: + include Net::LDAP::Instrumentation + LdapVersion = 3 MaxSaslChallenges = 10 @@ -1245,21 +1249,6 @@ def setup_encryption(args) end end - # Internal: Instrument a block with the defined instrumentation service. - # - # Returns the return value of the block. - def instrument(event, payload = {}) - return yield(payload) unless instrumentation_service - - instrumentation_service.instrument(event, payload) do |payload| - payload[:result] = yield(payload) - end - end - private :instrument - - attr_reader :instrumentation_service - private :instrumentation_service - #-- # This is provided as a convenience method to make sure a connection # object gets closed without waiting for a GC to happen. Clients shouldn't diff --git a/lib/net/ldap/instrumentation.rb b/lib/net/ldap/instrumentation.rb new file mode 100644 index 00000000..70db5a35 --- /dev/null +++ b/lib/net/ldap/instrumentation.rb @@ -0,0 +1,16 @@ +module Net::LDAP::Instrumentation + attr_reader :instrumentation_service + private :instrumentation_service + + # Internal: Instrument a block with the defined instrumentation service. + # + # Returns the return value of the block. + def instrument(event, payload = {}) + return yield(payload) unless instrumentation_service + + instrumentation_service.instrument(event, payload) do |payload| + payload[:result] = yield(payload) + end + end + private :instrument +end From b6a9c5aa353dae11461c376110c09c10513939ca Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 01:10:00 -0700 Subject: [PATCH 065/435] Instrument Net::LDAP#search --- lib/net/ldap.rb | 50 +++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 76175ea6..b19218e6 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -647,33 +647,35 @@ def search(args = {}) return_result_set = args[:return_result] != false result_set = return_result_set ? [] : nil - if @open_connection - @result = @open_connection.search(args) { |entry| - result_set << entry if result_set - yield entry if block_given? - } - else - begin - conn = Net::LDAP::Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.search(args) { |entry| - result_set << entry if result_set - yield entry if block_given? - } + instrument "search.net_ldap", args do |payload| + if @open_connection + @result = @open_connection.search(args) { |entry| + result_set << entry if result_set + yield entry if block_given? + } + else + begin + conn = Net::LDAP::Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.search(args) { |entry| + result_set << entry if result_set + yield entry if block_given? + } + end + ensure + conn.close if conn end - ensure - conn.close if conn end - end - if return_result_set - (!@result.nil? && @result.result_code == 0) ? result_set : nil - else - @result.success? + if return_result_set + (!@result.nil? && @result.result_code == 0) ? result_set : nil + else + @result.success? + end end end From 01be1a78640ff5cbdaa3dcf9c2a5b2bafad04ab2 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 01:18:42 -0700 Subject: [PATCH 066/435] Capture search result in instrumentation --- lib/net/ldap.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index b19218e6..bfc1e6ee 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1595,10 +1595,11 @@ def search(args = {}) break unless more_pages end # loop + # track total result count payload[:result_count] = n_results - end # instrument - result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") + result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") + end # instrument end MODIFY_OPERATIONS = { #:nodoc: From ba6408aea22db4b42dc339da72dba8ffc5d97530 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 17:12:42 -0700 Subject: [PATCH 067/435] Add lib/net/ldap/instrumentation.rb to Manifest, gemspec --- Manifest.txt | 1 + net-ldap.gemspec | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Manifest.txt b/Manifest.txt index 86cbea5f..bea51c0c 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -25,6 +25,7 @@ lib/net/ldap/dataset.rb lib/net/ldap/dn.rb lib/net/ldap/entry.rb lib/net/ldap/filter.rb +lib/net/ldap/instrumentation.rb lib/net/ldap/password.rb lib/net/ldap/pdu.rb lib/net/ldap/version.rb diff --git a/net-ldap.gemspec b/net-ldap.gemspec index cfac6ccd..854d4c6e 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -24,7 +24,7 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] + s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 8b5ecb68a4e4bc0f67ea1dc5f6995860d7115492 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 17:14:50 -0700 Subject: [PATCH 068/435] Spec out Net::LDAP#search instrumentation --- spec/unit/ldap/search_spec.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/spec/unit/ldap/search_spec.rb b/spec/unit/ldap/search_spec.rb index 5d06a88e..35adfb27 100644 --- a/spec/unit/ldap/search_spec.rb +++ b/spec/unit/ldap/search_spec.rb @@ -8,7 +8,8 @@ def search(args) end before(:each) do - @connection = Net::LDAP.new + @service = MockInstrumentationService.new + @connection = Net::LDAP.new :instrumentation_service => @service @connection.instance_variable_set(:@open_connection, FakeConnection.new) end @@ -32,4 +33,17 @@ def search(args) result_set.should be_nil end end + + context "when instrumentation_service is configured" do + it "should emit a search.net_ldap event" do + events = @service.subscribe "search.net_ldap" + + @connection.search :filter => "test" + + payload, result = events.pop + payload.should have_key(:result) + payload.should have_key(:filter) + payload[:filter].should == "test" + end + end end From 2101304b38c609d2bb250d944285d8fd449c3c7c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 17:21:02 -0700 Subject: [PATCH 069/435] Spec more consistently, separate --- spec/unit/ldap/search_spec.rb | 2 +- spec/unit/ldap_spec.rb | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/spec/unit/ldap/search_spec.rb b/spec/unit/ldap/search_spec.rb index 35adfb27..1a44f136 100644 --- a/spec/unit/ldap/search_spec.rb +++ b/spec/unit/ldap/search_spec.rb @@ -35,7 +35,7 @@ def search(args) end context "when instrumentation_service is configured" do - it "should emit a search.net_ldap event" do + it "should publish a search.net_ldap event" do events = @service.subscribe "search.net_ldap" @connection.search :filter => "test" diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index dc4c1a71..c76b8d8d 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -127,25 +127,35 @@ :instrumentation_service => @service) end - it "should publish a socket write event, followed by a socket read event" do + it "should publish a write.net_ldap_connection event" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) ber.ber_identifier = 7 - read_result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(read_result) + @tcp_socket.should_receive(:read_ber).and_return([2, ber]) - write_events = @service.subscribe "write.net_ldap_connection" - read_events = @service.subscribe "read.net_ldap_connection" + events = @service.subscribe "write.net_ldap_connection" - result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) + result = subject.bind(method: :anon) result.should be_success # a write event - payload, result = write_events.pop + payload, result = events.pop payload.should have_key(:result) payload.should have_key(:packet) + end + + it "should publish a read.net_ldap_connection event" do + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = 7 + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) + + events = @service.subscribe "read.net_ldap_connection" + + result = subject.bind(method: :anon) + result.should be_success - # then a read event - payload, result = read_events.pop + # a read event + payload, result = events.pop payload.should have_key(:result) result.should == read_result end From 67e17a28758800fec2e26a8ad9060e69d0aaf6e5 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 18:00:58 -0700 Subject: [PATCH 070/435] Spec out search.net_ldap_connection event --- spec/unit/ldap_spec.rb | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index c76b8d8d..e87160a2 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -117,8 +117,11 @@ context "instrumentation" do before do @tcp_socket = flexmock(:connection) + # handle write @tcp_socket.should_receive(:write) + # return this mock flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + @service = MockInstrumentationService.new end @@ -130,7 +133,8 @@ it "should publish a write.net_ldap_connection event" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) ber.ber_identifier = 7 - @tcp_socket.should_receive(:read_ber).and_return([2, ber]) + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) events = @service.subscribe "write.net_ldap_connection" @@ -159,5 +163,33 @@ payload.should have_key(:result) result.should == read_result end + + it "should publish a search.net_ldap_connection event" do + # search data + search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ + "uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local", + [ ["uid", ["user1"]] ] + ]]) + search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData + search_data = [2, search_data_ber] + # search result (end of results) + search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult + search_result = [2, search_result_ber] + @tcp_socket.should_receive(:read_ber).and_return(search_data). + and_return(search_result) + + events = @service.subscribe "search.net_ldap_connection" + + result = subject.search(filter: "(uid=user1)") + result.should be_success + + # a search event + payload, result = events.pop + payload.should have_key(:result) + payload.should have_key(:filter) + payload[:filter].to_s.should == "(uid=user1)" + result.should be_truthy + end end end From c2fde1aa486e71b1f76faad5ba78e60b6a184710 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 18:03:13 -0700 Subject: [PATCH 071/435] :nail_polish: trailing whitespace --- lib/net/ldap.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index bfc1e6ee..161167a3 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -258,7 +258,7 @@ class LdapError < StandardError; end DerefAliases_Find = 2 DerefAliases_Always = 3 DerefAliasesArray = [ DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always ] - + primitive = { 2 => :null } # UnbindRequest body constructed = { 0 => :array, # BindRequest @@ -1139,7 +1139,7 @@ def search_subschema_entry def paged_searches_supported? # active directory returns that it supports paged results. However # it returns binary data in the rfc2696_cookie which throws an - # encoding exception breaking searching. + # encoding exception breaking searching. return false if @force_no_page @server_caps ||= search_root_dse @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) @@ -1454,7 +1454,7 @@ def search(args = {}) deref = args[:deref] || Net::LDAP::DerefAliases_Never raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) - + # An interesting value for the size limit would be close to A/D's # built-in page limit of 1000 records, but openLDAP newer than version # 2.2.0 chokes on anything bigger than 126. You get a silent error that From fcdd78be931f82a550981048e227ded9d46408e1 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 26 Aug 2014 18:09:07 -0700 Subject: [PATCH 072/435] Use BER identifier constants, fix some packet types --- lib/net/ldap.rb | 14 +++++++------- spec/unit/ldap_spec.rb | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 161167a3..3925cf46 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1534,10 +1534,10 @@ def search(args = {}) while (be = read) && (pdu = Net::LDAP::PDU.new(be)) case pdu.app_tag - when 4 # search-data + when Net::LDAP::PDU::SearchReturnedData n_results += 1 yield pdu.search_entry if block_given? - when 19 # search-referral + when Net::LDAP::PDU::SearchResultReferral if return_referrals if block_given? se = Net::LDAP::Entry.new @@ -1545,7 +1545,7 @@ def search(args = {}) yield se end end - when 5 # search-result + when Net::LDAP::PDU::SearchResult result_pdu = pdu controls = pdu.result_controls if return_referrals && pdu.result_code == 10 @@ -1638,7 +1638,7 @@ def modify(args) pkt = [ next_msgid.to_ber, request ].to_ber_sequence write pkt - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end @@ -1663,7 +1663,7 @@ def add(args) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && - (pdu.app_tag == 9) or + (pdu.app_tag == Net::LDAP::PDU::AddResponse) or raise Net::LDAP::LdapError, "response missing or invalid" pdu @@ -1685,7 +1685,7 @@ def rename(args) write pkt (be = read) && - (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == 13) or + (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or raise Net::LDAP::LdapError.new( "response missing or invalid" ) pdu @@ -1701,7 +1701,7 @@ def delete(args) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence write pkt - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid" + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index e87160a2..d7b6bbc1 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -20,7 +20,7 @@ read_events = @service.subscribe "read.net_ldap_connection" ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = 7 + ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) @@ -95,7 +95,7 @@ it "should get back error messages if operation fails" do ber = Net::BER::BerIdentifiedArray.new([53, "", "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 = 7 + ber.ber_identifier = Net::LDAP::PDU::ModifyResponse @tcp_socket.should_receive(:read_ber).and_return([2, ber]) result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) @@ -105,7 +105,7 @@ it "shouldn't get back error messages if operation succeeds" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = 7 + ber.ber_identifier = Net::LDAP::PDU::ModifyResponse @tcp_socket.should_receive(:read_ber).and_return([2, ber]) result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) @@ -132,7 +132,7 @@ it "should publish a write.net_ldap_connection event" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = 7 + ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) @@ -149,11 +149,11 @@ it "should publish a read.net_ldap_connection event" do ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = 7 + ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) - events = @service.subscribe "read.net_ldap_connection" + events = @service.subscribe "read.net_ldap_connection" result = subject.bind(method: :anon) result.should be_success From 544c29ed4ed680f59be15e7e8af31cfd5a3b52cb Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:14:28 -0700 Subject: [PATCH 073/435] Rewrite #instrument Only yields if block is given so #instrument can be called without one. Clarifies conditional behavior when service is set. --- lib/net/ldap/instrumentation.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/instrumentation.rb b/lib/net/ldap/instrumentation.rb index 70db5a35..1cc8b381 100644 --- a/lib/net/ldap/instrumentation.rb +++ b/lib/net/ldap/instrumentation.rb @@ -6,10 +6,12 @@ module Net::LDAP::Instrumentation # # Returns the return value of the block. def instrument(event, payload = {}) - return yield(payload) unless instrumentation_service - - instrumentation_service.instrument(event, payload) do |payload| - payload[:result] = yield(payload) + if instrumentation_service + instrumentation_service.instrument(event, payload) do |payload| + payload[:result] = yield(payload) if block_given? + end + else + yield(payload) if block_given? end end private :instrument From 6c4ada5e0de093033f5f465701454a7657aeb96d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:16:29 -0700 Subject: [PATCH 074/435] Clarify method docs for #instrument --- lib/net/ldap/instrumentation.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/net/ldap/instrumentation.rb b/lib/net/ldap/instrumentation.rb index 1cc8b381..83724c5a 100644 --- a/lib/net/ldap/instrumentation.rb +++ b/lib/net/ldap/instrumentation.rb @@ -4,6 +4,10 @@ module Net::LDAP::Instrumentation # Internal: Instrument a block with the defined instrumentation service. # + # Yields the event payload if a block is given. + # + # Skips instrumentation if no service is set. + # # Returns the return value of the block. def instrument(event, payload = {}) if instrumentation_service From ca5f740feade67ed30002bd4ec4e6e20421ec675 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:26:56 -0700 Subject: [PATCH 075/435] Include instrumentation_service with all new Connections --- lib/net/ldap.rb | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 3925cf46..8a50b7bb 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -845,8 +845,11 @@ def add(args) else @result = 0 begin - conn = Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.add(args) end @@ -943,8 +946,11 @@ def modify(args) else @result = 0 begin - conn = Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.modify(args) end @@ -1015,8 +1021,11 @@ def rename(args) else @result = 0 begin - conn = Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.rename(args) end @@ -1043,8 +1052,11 @@ def delete(args) else @result = 0 begin - conn = Connection.new(:host => @host, :port => @port, - :encryption => @encryption) + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 @result = conn.delete(args) end From 79c04ce56cd43c30732ec97b1722e1a7e02a2de0 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:34:58 -0700 Subject: [PATCH 076/435] Document the #write, #read methods --- lib/net/ldap.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 8a50b7bb..82477aab 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1273,6 +1273,11 @@ def close @conn = nil end + # Internal: Reads and parses data from the configured connection. + # + # - syntax: the BER syntax to use to parse the read data with + # + # Returns basic BER objects. def read(syntax = Net::LDAP::AsnSyntax) instrument "read.net_ldap_connection", :syntax => syntax do |payload| @conn.read_ber(syntax) do |id, content_length| @@ -1283,6 +1288,12 @@ def read(syntax = Net::LDAP::AsnSyntax) end private :read + # Internal: Writes the given packet to the configured connection. + # + # - packet: the BER data packet to write on the socket. + # + # Returns the return value from writing to the connection, which in some + # cases is the Integer number of bytes written to the socket. def write(packet) instrument "write.net_ldap_connection", :packet => packet do @conn.write(packet) From 256c7c5ee06fbbd58e4b31def6ec37ff733e68fa Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:46:44 -0700 Subject: [PATCH 077/435] Replace packet in write event payload with content_length --- lib/net/ldap.rb | 4 ++-- spec/unit/ldap_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 82477aab..b78654ef 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1295,8 +1295,8 @@ def read(syntax = Net::LDAP::AsnSyntax) # Returns the return value from writing to the connection, which in some # cases is the Integer number of bytes written to the socket. def write(packet) - instrument "write.net_ldap_connection", :packet => packet do - @conn.write(packet) + instrument "write.net_ldap_connection" do |payload| + payload[:content_length] = @conn.write(packet) end end private :write diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index d7b6bbc1..67854af2 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -144,7 +144,7 @@ # a write event payload, result = events.pop payload.should have_key(:result) - payload.should have_key(:packet) + payload.should have_key(:content_length) end it "should publish a read.net_ldap_connection event" do From 4f035100dfcbf3c7a44cb83b45876b7a4b8d2573 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:47:04 -0700 Subject: [PATCH 078/435] Rename response_id to object_type_id --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index b78654ef..0a78e56c 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1281,7 +1281,7 @@ def close def read(syntax = Net::LDAP::AsnSyntax) instrument "read.net_ldap_connection", :syntax => syntax do |payload| @conn.read_ber(syntax) do |id, content_length| - payload[:response_id] = id + payload[:object_type_id] = id payload[:content_length] = content_length end end From 1829cd66ef015b9d13c4f7bc65d4af7ef79fbef1 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 00:58:33 -0700 Subject: [PATCH 079/435] Yield id, content_length even if indeterminate length Turns out this could be useful even if it's unsupported. Includes documentation. --- lib/net/ber/ber_parser.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/net/ber/ber_parser.rb b/lib/net/ber/ber_parser.rb index 47379b87..ea6c0788 100644 --- a/lib/net/ber/ber_parser.rb +++ b/lib/net/ber/ber_parser.rb @@ -148,6 +148,9 @@ def read_ber_length # implemented on the including object and that it returns a Fixnum value. # Also requires #read(bytes) to work. # + # Yields the object type `id` and the data `content_length` if a block is + # given. This is namely to support instrumentation. + # # This does not work with non-blocking I/O. def read_ber(syntax = nil) # TODO: clean this up so it works properly with partial packets coming @@ -157,10 +160,11 @@ def read_ber(syntax = nil) id = getbyte or return nil # don't trash this value, we'll use it later content_length = read_ber_length + yield id, content_length if block_given? + if -1 == content_length raise Net::BER::BerError, "Indeterminite BER content length not implemented." else - yield id, content_length if block_given? data = read(content_length) end From 5334dfda2b8dfbb69636d4d0dc84fd007c7d8a5e Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 01:24:38 -0700 Subject: [PATCH 080/435] Document instrumentation_service param for Net::LDAP.new --- lib/net/ldap.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 0a78e56c..22c00d4d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -385,6 +385,8 @@ def self.result2string(code) #:nodoc: # #encryption for details. # * :force_no_page => Set to true to prevent paged results even if your # server says it supports them. This is a fix for MS Active Directory + # * :instrumentation_service => An object responsible for instrumenting + # operations, compatible with ActiveSupport::Notifications' public API. # # Instantiating a Net::LDAP object does not result in network # traffic to the LDAP server. It simply stores the connection and binding From 80266c9615f63a955e135283b89159ed272d53e7 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 01:36:44 -0700 Subject: [PATCH 081/435] ALlow failures from jruby 1.9 --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9e097a28..6877e706 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,7 @@ rvm: - 2.0.0 - jruby-19mode - rbx-19mode +matrix: + allow_failures: + - rvm: jruby-19mode script: bundle exec rake spec From 2e0f0fef9a33e046db2aaa0976ca4848515492bd Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 27 Aug 2014 02:14:42 -0700 Subject: [PATCH 082/435] Support version: when parsing LDIF to Dataset --- lib/net/ldap/dataset.rb | 15 +++++++++++++-- test/test_ldif.rb | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/dataset.rb b/lib/net/ldap/dataset.rb index ffdee11f..9f3c46fe 100644 --- a/lib/net/ldap/dataset.rb +++ b/lib/net/ldap/dataset.rb @@ -4,11 +4,13 @@ # to and from LDIF strings and Net::LDAP::Entry objects. class Net::LDAP::Dataset < Hash ## - # Dataset object comments. - attr_reader :comments + # Dataset object version, comments. + attr_accessor :version + attr_reader :comments def initialize(*args, &block) # :nodoc: super + @version = nil @comments = [] end @@ -17,6 +19,12 @@ def initialize(*args, &block) # :nodoc: # entries. def to_ldif ary = [] + + if version + ary << "version: #{version}" + ary << "" + end + ary += @comments unless @comments.empty? keys.sort.each do |dn| ary << "dn: #{dn}" @@ -125,6 +133,9 @@ def read_ldif(io) if line =~ /^#/ ds.comments << line yield :comment, line if block_given? + elsif line =~ /^version:[\s]*([0-9]+)$/i + ds.version = $1 + yield :version, line if block_given? elsif line =~ /^dn:[\s]*/i dn = $' ds[dn] = Hash.new { |k,v| k[v] = [] } diff --git a/test/test_ldif.rb b/test/test_ldif.rb index fb4d5ee9..70436826 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -13,6 +13,12 @@ def test_empty_ldif assert_equal(true, ds.empty?) end + def test_ldif_with_version + io = StringIO.new("version: 1") + ds = Net::LDAP::Dataset.read_ldif(io) + assert_equal "1", ds.version + end + def test_ldif_with_comments str = ["# Hello from LDIF-land", "# This is an unterminated comment"] io = StringIO.new(str[0] + "\r\n" + str[1]) @@ -76,4 +82,11 @@ def test_to_ldif assert_equal(entries.size, ds.size) assert_equal(entries.sort, ds.to_ldif.grep(/^dn:\s*/) { $'.chomp }) end + + def test_to_ldif_with_version + ds = Net::LDAP::Dataset.new + ds.version = "1" + + assert_equal "version: 1", ds.to_ldif_string.chomp + end end From 4502c12c8ee94d670c3d54d9d362518f564a9990 Mon Sep 17 00:00:00 2001 From: Antoine Delvaux Date: Thu, 28 Aug 2014 13:57:45 +0000 Subject: [PATCH 083/435] Correcting documentation format of ldap.modify(). --- lib/net/ldap.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 948fddaa..8f66f72f 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -866,9 +866,10 @@ def add(args) # operations in order. # # Each of the operations appearing in the Array must itself be an Array - # with exactly three elements: an operator:: must be :add, :replace, or - # :delete an attribute name:: the attribute name (string or symbol) to - # modify a value:: either a string or an array of strings. + # with exactly three elements: + # an operator :: must be :add, :replace, or :delete + # an attribute name :: the attribute name (string or symbol) to modify + # a value :: either a string or an array of strings. # # The :add operator will, unsurprisingly, add the specified values to the # specified attribute. If the attribute does not already exist, :add will @@ -911,13 +912,13 @@ def add(args) # may not get extended information that will tell you which one failed. # #modify has no notion of an atomic transaction. If you specify a chain # of modifications in one call to #modify, and one of them fails, the - # preceding ones will usually not be "rolled back, " resulting in a + # preceding ones will usually not be "rolled back", resulting in a # partial update. This is a limitation of the LDAP protocol, not of # Net::LDAP. # # The lack of transactional atomicity in LDAP means that you're usually # better off using the convenience methods #add_attribute, - # #replace_attribute, and #delete_attribute, which are are wrappers over + # #replace_attribute, and #delete_attribute, which are wrappers over # #modify. However, certain LDAP servers may provide concurrency # semantics, in which the several operations contained in a single #modify # call are not interleaved with other modification-requests received From f7ba771a3993a9663eef681fe0c5d39f4ba63fd0 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 21:03:28 -0700 Subject: [PATCH 084/435] Instrument Net::LDAP#open --- lib/net/ldap.rb | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 22c00d4d..6fe62019 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -577,18 +577,21 @@ def open # all generate auth failures if the bind was unsuccessful. raise Net::LDAP::LdapError, "Open already in progress" if @open_connection - begin - @open_connection = - Net::LDAP::Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - @open_connection.bind(@auth) - yield self - ensure - @open_connection.close if @open_connection - @open_connection = nil + instrument "open.net_ldap" do |payload| + begin + @open_connection = + Net::LDAP::Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + payload[:connection] = @open_connection + payload[:bind] = @open_connection.bind(@auth) + yield self + ensure + @open_connection.close if @open_connection + @open_connection = nil + end end end From 2b0be68d05a35ebb8ecb9a86e77f625410b50fb7 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 21:05:08 -0700 Subject: [PATCH 085/435] Instrument Net::LDAP#bind --- lib/net/ldap.rb | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 6fe62019..61da4c4f 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -742,22 +742,26 @@ def search(args = {}) # the documentation for #auth, the password parameter can be a Ruby Proc # instead of a String. def bind(auth = @auth) - if @open_connection - @result = @open_connection.bind(auth) - else - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - @result = conn.bind(auth) - ensure - conn.close if conn + instrument "bind.net_ldap" do |payload| + if @open_connection + payload[:connection] = @open_connection + payload[:bind] = @result = @open_connection.bind(auth) + else + begin + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + payload[:connection] = conn + payload[:bind] = @result = conn.bind(auth) + ensure + conn.close if conn + end end - end - @result.success? + @result.success? + end end # #bind_as is for testing authentication credentials. From 08dad4269e466b653233eb1581d3af5a019a790d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 21:10:27 -0700 Subject: [PATCH 086/435] Minor :nail_care: for Net::LDAP instrumentation specs --- spec/unit/ldap_spec.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 67854af2..5b67acbd 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -2,7 +2,7 @@ describe Net::LDAP do describe "initialize" do - context "on instrumentation_service configuration" do + context "when instrumentation is configured" do before do @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:close) @@ -10,10 +10,13 @@ @service = MockInstrumentationService.new end - it "should set the service object and instrument network calls" do - ldap = Net::LDAP.new(:server => 'test.mocked.com', :port => 636, - :instrumentation_service => @service) + subject do + Net::LDAP.new \ + :server => "test.mocked.com", :port => 636, + :instrumentation_service => @service + end + it "should set the service object and instrument network calls" do @tcp_socket.should_receive(:write).and_return(bytes_written = 1) write_events = @service.subscribe "write.net_ldap_connection" @@ -24,7 +27,7 @@ read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) - ldap.bind.should be_true + subject.bind.should be_true # a write event payload, result = write_events.pop From 84dfde7f6a1a208f20d0f1b3769e5c62f4f2dbc6 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 22:02:50 -0700 Subject: [PATCH 087/435] Spec out Net::LDAP#bind instrumentation Pretty much removes what was there before since it was re-specing Net::LDAP::Connection#bind and wire level instrumentation. --- spec/unit/ldap_spec.rb | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 5b67acbd..4ae0cf8e 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -4,9 +4,9 @@ describe "initialize" do context "when instrumentation is configured" do before do - @tcp_socket = flexmock(:connection) - @tcp_socket.should_receive(:close) - flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + @connection = flexmock(:connection, :close => true) + flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection) + @service = MockInstrumentationService.new end @@ -16,26 +16,20 @@ :instrumentation_service => @service end - it "should set the service object and instrument network calls" do - @tcp_socket.should_receive(:write).and_return(bytes_written = 1) - - write_events = @service.subscribe "write.net_ldap_connection" - read_events = @service.subscribe "read.net_ldap_connection" + it "should instrument bind" do + events = @service.subscribe "bind.net_ldap" - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(read_result) + # ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + # ber.ber_identifier = Net::LDAP::PDU::BindResult + # Net::LDAP::PDU.new([0, ber]) + bind_result = flexmock(:bind_result, :success? => true) + @connection.should_receive(:bind).with(Hash).and_return(bind_result) subject.bind.should be_true - # a write event - payload, result = write_events.pop - result.should == bytes_written - - # then a read event - payload, result = read_events.pop - result.should == read_result + payload, result = events.pop + result.should be_true + payload[:bind].should == bind_result end end end From bcf25058946f9222dd4a2bc7eb3c19fb9099d5be Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 22:06:20 -0700 Subject: [PATCH 088/435] Whoops, don't need this --- spec/unit/ldap_spec.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 4ae0cf8e..e7ab6b01 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -19,9 +19,6 @@ it "should instrument bind" do events = @service.subscribe "bind.net_ldap" - # ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - # ber.ber_identifier = Net::LDAP::PDU::BindResult - # Net::LDAP::PDU.new([0, ber]) bind_result = flexmock(:bind_result, :success? => true) @connection.should_receive(:bind).with(Hash).and_return(bind_result) From 5e9b73563be11d81c7c91609dade0ac7c41394c1 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 22:35:42 -0700 Subject: [PATCH 089/435] Spec out Net::LDAP#search instrumentation --- spec/unit/ldap_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index e7ab6b01..341dec25 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -13,6 +13,7 @@ subject do Net::LDAP.new \ :server => "test.mocked.com", :port => 636, + :force_no_page => true, # so server capabilities are not queried :instrumentation_service => @service end @@ -28,6 +29,22 @@ result.should be_true payload[:bind].should == bind_result end + + it "should instrument search" do + events = @service.subscribe "search.net_ldap" + + @connection.should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + @connection.should_receive(:search).with(Hash, Proc). + yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). + and_return(flexmock(:search_result, :success? => true, :result_code => 0)) + + subject.search(:filter => "(uid=user1)").should be_true + + payload, result = events.pop + result.should == [entry] + payload[:result].should == [entry] + payload[:filter].should == "(uid=user1)" + end end end end From 910b13e9d673ed94e717ffb93db93251cf255d40 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 22:48:40 -0700 Subject: [PATCH 090/435] Instrument Net::LDAP#add, #modify, #delete, #rename --- lib/net/ldap.rb | 130 +++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 61da4c4f..ed5fd7d8 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -849,24 +849,26 @@ def bind_as(args = {}) # ldap.add(:dn => dn, :attributes => attr) # end def add(args) - if @open_connection - @result = @open_connection.add(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.add(args) + instrument "add.net_ldap", args do |payload| + if @open_connection + @result = @open_connection.add(args) + else + @result = 0 + begin + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.add(args) + end + ensure + conn.close if conn end - ensure - conn.close if conn end + @result.success? end - @result.success? end # Modifies the attribute values of a particular entry on the LDAP @@ -950,25 +952,27 @@ def add(args) # simultaneously by the server. It bears repeating that this concurrency # does _not_ imply transactional atomicity, which LDAP does not provide. def modify(args) - if @open_connection - @result = @open_connection.modify(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.modify(args) + instrument "modify.net_ldap", args do |payload| + if @open_connection + @result = @open_connection.modify(args) + else + @result = 0 + begin + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.modify(args) + end + ensure + conn.close if conn end - ensure - conn.close if conn end - end - @result.success? + @result.success? + end end # Add a value to an attribute. Takes the full DN of the entry to modify, @@ -1025,24 +1029,26 @@ def delete_attribute(dn, attribute) # # _Documentation_ _stub_ def rename(args) - if @open_connection - @result = @open_connection.rename(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.rename(args) + instrument "rename.net_ldap", args do |payload| + if @open_connection + @result = @open_connection.rename(args) + else + @result = 0 + begin + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.rename(args) + end + ensure + conn.close if conn end - ensure - conn.close if conn end + @result.success? end - @result.success? end alias_method :modify_rdn, :rename @@ -1056,24 +1062,26 @@ def rename(args) # dn = "mail=deleteme@example.com, ou=people, dc=example, dc=com" # ldap.delete :dn => dn def delete(args) - if @open_connection - @result = @open_connection.delete(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 - @result = conn.delete(args) + instrument "delete.net_ldap", args do |payload| + if @open_connection + @result = @open_connection.delete(args) + else + @result = 0 + begin + conn = Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + @result = conn.delete(args) + end + ensure + conn.close end - ensure - conn.close end + @result.success? end - @result.success? end # Delete an entry from the LDAP directory along with all subordinate entries. From 7c6f709f9f7ad19b021f1d872de4efc267f236c5 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sat, 30 Aug 2014 23:21:24 -0700 Subject: [PATCH 091/435] Ensure payload is distinct from what's passed in This is because we modify what comes in (with, at the very least, :result). --- lib/net/ldap/instrumentation.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap/instrumentation.rb b/lib/net/ldap/instrumentation.rb index 83724c5a..143e03b3 100644 --- a/lib/net/ldap/instrumentation.rb +++ b/lib/net/ldap/instrumentation.rb @@ -10,6 +10,7 @@ module Net::LDAP::Instrumentation # # Returns the return value of the block. def instrument(event, payload = {}) + payload = (payload || {}).dup if instrumentation_service instrumentation_service.instrument(event, payload) do |payload| payload[:result] = yield(payload) if block_given? From 0eebc66b22a5d7d86e55dda8ffd9b92a2b5b4392 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 31 Aug 2014 00:00:52 -0700 Subject: [PATCH 092/435] Update the build badge --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index affb1422..969a717a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -= Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap] += Net::LDAP for Ruby {}[https://travis-ci.org/github/ruby-net-ldap] == Description From 0bce7b2baf4708f37c7fe1d4591c097e85be27dc Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 3 Sep 2014 10:45:48 -0700 Subject: [PATCH 093/435] Instrument Net::LDAP::Connection#bind --- lib/net/ldap.rb | 20 +++++++++++--------- spec/unit/ldap_spec.rb | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index ed5fd7d8..8201d8f0 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1324,15 +1324,17 @@ def next_msgid end def bind(auth) - meth = auth[:method] - if [:simple, :anonymous, :anon].include?(meth) - bind_simple auth - elsif meth == :sasl - bind_sasl(auth) - elsif meth == :gss_spnego - bind_gss_spnego(auth) - else - raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" + instrument "bind.net_ldap_connection" do |payload| + payload[:method] = meth = auth[:method] + if [:simple, :anonymous, :anon].include?(meth) + bind_simple auth + elsif meth == :sasl + bind_sasl(auth) + elsif meth == :gss_spnego + bind_gss_spnego(auth) + else + raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" + end end end diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index 341dec25..af80f324 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -175,6 +175,23 @@ result.should == read_result end + it "should publish a bind.net_ldap_connection event" do + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::BindResult + bind_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(bind_result) + + events = @service.subscribe "bind.net_ldap_connection" + + result = subject.bind(method: :anon) + result.should be_success + + # a read event + payload, result = events.pop + payload.should have_key(:result) + result.should be_success + end + it "should publish a search.net_ldap_connection event" do # search data search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ From 449370b5cfeae01a1d9a425fa0e649462ae83840 Mon Sep 17 00:00:00 2001 From: Michael Schaarschmidt Date: Wed, 10 Sep 2014 11:31:13 +0200 Subject: [PATCH 094/435] push version to 0.8.0 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 36334574..155ca49c 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.7.0" + VERSION = "0.8.0" end end From 6dd3cedca8950efa76d5a1a9762beb031fa6dc65 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sat, 20 Sep 2014 19:40:56 -0700 Subject: [PATCH 095/435] fix spec deprecations --- spec/unit/ber/ber_spec.rb | 11 +++++------ spec/unit/ldap/search_spec.rb | 2 +- spec/unit/ldap_spec.rb | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 9806cc85..68242c43 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -90,8 +90,7 @@ raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") end it "should not fail on strings that can not be converted to UTF-8" do - error = Encoding::UndefinedConversionError - lambda {"\x81".to_ber }.should_not raise_exception(error) + expect { "\x81".to_ber }.not_to raise_error end end end @@ -120,21 +119,21 @@ context "binary data" do let(:data) { ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") } - its(:valid_encoding?) { should be_true } + specify { subject.valid_encoding?.should == true } specify { subject.encoding.name.should == "ASCII-8BIT" } end context "ascii data in UTF-8" do let(:data) { "some text".force_encoding("UTF-8") } - its(:valid_encoding?) { should be_true } + specify { subject.valid_encoding?.should == true } specify { subject.encoding.name.should == "UTF-8" } end context "UTF-8 data in UTF-8" do let(:data) { ["e4b8ad"].pack("H*").force_encoding("UTF-8") } - - its(:valid_encoding?) { should be_true } + + specify { subject.valid_encoding?.should == true } specify { subject.encoding.name.should == "UTF-8" } end end diff --git a/spec/unit/ldap/search_spec.rb b/spec/unit/ldap/search_spec.rb index 1a44f136..55aa94db 100644 --- a/spec/unit/ldap/search_spec.rb +++ b/spec/unit/ldap/search_spec.rb @@ -23,7 +23,7 @@ def search(args) context "when :return_result => false" do it "should return false upon error" do result = @connection.search(:return_result => false) - result.should be_false + result.should == false end end diff --git a/spec/unit/ldap_spec.rb b/spec/unit/ldap_spec.rb index af80f324..8f756b68 100644 --- a/spec/unit/ldap_spec.rb +++ b/spec/unit/ldap_spec.rb @@ -23,10 +23,10 @@ bind_result = flexmock(:bind_result, :success? => true) @connection.should_receive(:bind).with(Hash).and_return(bind_result) - subject.bind.should be_true + subject.bind.should == true payload, result = events.pop - result.should be_true + result.should == true payload[:bind].should == bind_result end @@ -38,7 +38,7 @@ yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). and_return(flexmock(:search_result, :success? => true, :result_code => 0)) - subject.search(:filter => "(uid=user1)").should be_true + subject.search(:filter => "(uid=user1)").should_not be_nil payload, result = events.pop result.should == [entry] From 536e2ea1f542aa25ed2799f9d688203c331a17a5 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sun, 5 Oct 2014 10:12:00 -0700 Subject: [PATCH 096/435] remove redundant spec.opts --- spec/spec.opts | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 spec/spec.opts diff --git a/spec/spec.opts b/spec/spec.opts deleted file mode 100644 index d019bfbf..00000000 --- a/spec/spec.opts +++ /dev/null @@ -1,2 +0,0 @@ ---format specdoc ---colour \ No newline at end of file From 202a45c8724d69acffe73ca38f774d7b3eea7924 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sun, 5 Oct 2014 10:27:58 -0700 Subject: [PATCH 097/435] move Net::LDAP::Connection to it's own file --- lib/net/ldap.rb | 575 +------------------------------------ lib/net/ldap/connection.rb | 573 ++++++++++++++++++++++++++++++++++++ 2 files changed, 574 insertions(+), 574 deletions(-) create mode 100644 lib/net/ldap/connection.rb diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 5effe57a..8fb9107e 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -24,6 +24,7 @@ class LDAP require 'net/ldap/password' require 'net/ldap/entry' require 'net/ldap/instrumentation' +require 'net/ldap/connection' require 'net/ldap/version' # == Quick-start for the Impatient @@ -1175,577 +1176,3 @@ def paged_searches_supported? @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) end end # class LDAP - -# This is a private class used internally by the library. It should not -# be called by user code. -class Net::LDAP::Connection #:nodoc: - include Net::LDAP::Instrumentation - - LdapVersion = 3 - MaxSaslChallenges = 10 - - def initialize(server) - @instrumentation_service = server[:instrumentation_service] - - begin - @conn = TCPSocket.new(server[:host], server[:port]) - rescue SocketError - raise Net::LDAP::LdapError, "No such address or other socket error." - rescue Errno::ECONNREFUSED - raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." - end - - if server[:encryption] - setup_encryption server[:encryption] - end - - yield self if block_given? - end - - module GetbyteForSSLSocket - def getbyte - getc.ord - end - end - - module FixSSLSocketSyncClose - def close - super - io.close - end - end - - def self.wrap_with_ssl(io) - raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL - ctx = OpenSSL::SSL::SSLContext.new - conn = OpenSSL::SSL::SSLSocket.new(io, ctx) - conn.connect - - # Doesn't work: - # conn.sync_close = true - - conn.extend(GetbyteForSSLSocket) unless conn.respond_to?(:getbyte) - conn.extend(FixSSLSocketSyncClose) - - conn - end - - #-- - # Helper method called only from new, and only after we have a - # successfully-opened @conn instance variable, which is a TCP connection. - # Depending on the received arguments, we establish SSL, potentially - # replacing the value of @conn accordingly. Don't generate any errors here - # if no encryption is requested. DO raise Net::LDAP::LdapError objects if encryption - # is requested and we have trouble setting it up. That includes if OpenSSL - # is not set up on the machine. (Question: how does the Ruby OpenSSL - # wrapper react in that case?) DO NOT filter exceptions raised by the - # OpenSSL library. Let them pass back to the user. That should make it - # easier for us to debug the problem reports. Presumably (hopefully?) that - # will also produce recognizable errors if someone tries to use this on a - # machine without OpenSSL. - # - # The simple_tls method is intended as the simplest, stupidest, easiest - # solution for people who want nothing more than encrypted comms with the - # LDAP server. It doesn't do any server-cert validation and requires - # nothing in the way of key files and root-cert files, etc etc. OBSERVE: - # WE REPLACE the value of @conn, which is presumed to be a connected - # TCPSocket object. - # - # The start_tls method is supported by many servers over the standard LDAP - # port. It does not require an alternative port for encrypted - # communications, as with simple_tls. Thanks for Kouhei Sutou for - # generously contributing the :start_tls path. - #++ - def setup_encryption(args) - case args[:method] - when :simple_tls - @conn = self.class.wrap_with_ssl(@conn) - # additional branches requiring server validation and peer certs, etc. - # go here. - when :start_tls - msgid = next_msgid.to_ber - request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt - be = read - raise Net::LDAP::LdapError, "no start_tls result" if be.nil? - pdu = Net::LDAP::PDU.new(be) - raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? - if pdu.result_code.zero? - @conn = self.class.wrap_with_ssl(@conn) - else - raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" - end - else - raise Net::LDAP::LdapError, "unsupported encryption method #{args[:method]}" - end - end - - #-- - # This is provided as a convenience method to make sure a connection - # object gets closed without waiting for a GC to happen. Clients shouldn't - # have to call it, but perhaps it will come in handy someday. - #++ - def close - @conn.close - @conn = nil - end - - # Internal: Reads and parses data from the configured connection. - # - # - syntax: the BER syntax to use to parse the read data with - # - # Returns basic BER objects. - def read(syntax = Net::LDAP::AsnSyntax) - instrument "read.net_ldap_connection", :syntax => syntax do |payload| - @conn.read_ber(syntax) do |id, content_length| - payload[:object_type_id] = id - payload[:content_length] = content_length - end - end - end - private :read - - # Internal: Writes the given packet to the configured connection. - # - # - packet: the BER data packet to write on the socket. - # - # Returns the return value from writing to the connection, which in some - # cases is the Integer number of bytes written to the socket. - def write(packet) - instrument "write.net_ldap_connection" do |payload| - payload[:content_length] = @conn.write(packet) - end - end - private :write - - def next_msgid - @msgid ||= 0 - @msgid += 1 - end - - def bind(auth) - instrument "bind.net_ldap_connection" do |payload| - payload[:method] = meth = auth[:method] - if [:simple, :anonymous, :anon].include?(meth) - bind_simple auth - elsif meth == :sasl - bind_sasl(auth) - elsif meth == :gss_spnego - bind_gss_spnego(auth) - else - raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" - end - end - end - - #-- - # Implements a simple user/psw authentication. Accessed by calling #bind - # with a method of :simple or :anonymous. - #++ - def bind_simple(auth) - user, psw = if auth[:method] == :simple - [auth[:username] || auth[:dn], auth[:password]] - else - ["", ""] - end - - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) - - msgid = next_msgid.to_ber - request = [LdapVersion.to_ber, user.to_ber, - psw.to_ber_contextspecific(0)].to_ber_appsequence(0) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt - - (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" - - pdu - end - - #-- - # Required parameters: :mechanism, :initial_credential and - # :challenge_response - # - # Mechanism is a string value that will be passed in the SASL-packet's - # "mechanism" field. - # - # Initial credential is most likely a string. It's passed in the initial - # BindRequest that goes to the server. In some protocols, it may be empty. - # - # Challenge-response is a Ruby proc that takes a single parameter and - # returns an object that will typically be a string. The - # challenge-response block is called when the server returns a - # BindResponse with a result code of 14 (saslBindInProgress). The - # challenge-response block receives a parameter containing the data - # returned by the server in the saslServerCreds field of the LDAP - # BindResponse packet. The challenge-response block may be called multiple - # times during the course of a SASL authentication, and each time it must - # return a value that will be passed back to the server as the credential - # data in the next BindRequest packet. - #++ - def bind_sasl(auth) - mech, cred, chall = auth[:mechanism], auth[:initial_credential], - auth[:challenge_response] - raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall) - - n = 0 - loop { - msgid = next_msgid.to_ber - sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) - request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt - - (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" - return pdu unless pdu.result_code == 14 # saslBindInProgress - raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) - - cred = chall.call(pdu.result_server_sasl_creds) - } - - raise Net::LDAP::LdapError, "why are we here?" - end - private :bind_sasl - - #-- - # PROVISIONAL, only for testing SASL implementations. DON'T USE THIS YET. - # Uses Kohei Kajimoto's Ruby/NTLM. We have to find a clean way to - # integrate it without introducing an external dependency. - # - # This authentication method is accessed by calling #bind with a :method - # parameter of :gss_spnego. It requires :username and :password - # attributes, just like the :simple authentication method. It performs a - # GSS-SPNEGO authentication with the server, which is presumed to be a - # Microsoft Active Directory. - #++ - def bind_gss_spnego(auth) - require 'ntlm' - - user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) - - nego = proc { |challenge| - t2_msg = NTLM::Message.parse(challenge) - t3_msg = t2_msg.response({ :user => user, :password => psw }, - { :ntlmv2 => true }) - t3_msg.serialize - } - - bind_sasl(:method => :sasl, :mechanism => "GSS-SPNEGO", - :initial_credential => NTLM::Message::Type1.new.serialize, - :challenge_response => nego) - end - private :bind_gss_spnego - - - #-- - # Allow the caller to specify a sort control - # - # The format of the sort control needs to be: - # - # :sort_control => ["cn"] # just a string - # or - # :sort_control => [["cn", "matchingRule", true]] #attribute, matchingRule, direction (true / false) - # or - # :sort_control => ["givenname","sn"] #multiple strings or arrays - # - def encode_sort_controls(sort_definitions) - return sort_definitions unless sort_definitions - - sort_control_values = sort_definitions.map do |control| - control = Array(control) # if there is only an attribute name as a string then infer the orderinrule and reverseorder - control[0] = String(control[0]).to_ber, - control[1] = String(control[1]).to_ber, - control[2] = (control[2] == true).to_ber - control.to_ber_sequence - end - sort_control = [ - Net::LDAP::LDAPControls::SORT_REQUEST.to_ber, - false.to_ber, - sort_control_values.to_ber_sequence.to_s.to_ber - ].to_ber_sequence - end - - #-- - # Alternate implementation, this yields each search entry to the caller as - # it are received. - # - # TODO: certain search parameters are hardcoded. - # TODO: if we mis-parse the server results or the results are wrong, we - # can block forever. That's because we keep reading results until we get a - # type-5 packet, which might never come. We need to support the time-limit - # in the protocol. - #++ - def search(args = {}) - search_filter = (args && args[:filter]) || - Net::LDAP::Filter.eq("objectclass", "*") - search_filter = Net::LDAP::Filter.construct(search_filter) if search_filter.is_a?(String) - search_base = (args && args[:base]) || "dc=example, dc=com" - search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber} - return_referrals = args && args[:return_referrals] == true - sizelimit = (args && args[:size].to_i) || 0 - raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0 - paged_searches_supported = (args && args[:paged_searches_supported]) - - attributes_only = (args and args[:attributes_only] == true) - scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree - raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) - - sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) - - deref = args[:deref] || Net::LDAP::DerefAliases_Never - raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) - - - # An interesting value for the size limit would be close to A/D's - # built-in page limit of 1000 records, but openLDAP newer than version - # 2.2.0 chokes on anything bigger than 126. You get a silent error that - # is easily visible by running slapd in debug mode. Go figure. - # - # Changed this around 06Sep06 to support a caller-specified search-size - # limit. Because we ALWAYS do paged searches, we have to work around the - # problem that it's not legal to specify a "normal" sizelimit (in the - # body of the search request) that is larger than the page size we're - # requesting. Unfortunately, I have the feeling that this will break - # with LDAP servers that don't support paged searches!!! - # - # (Because we pass zero as the sizelimit on search rounds when the - # remaining limit is larger than our max page size of 126. In these - # cases, I think the caller's search limit will be ignored!) - # - # CONFIRMED: This code doesn't work on LDAPs that don't support paged - # searches when the size limit is larger than 126. We're going to have - # to do a root-DSE record search and not do a paged search if the LDAP - # doesn't support it. Yuck. - rfc2696_cookie = [126, ""] - result_pdu = nil - n_results = 0 - - instrument "search.net_ldap_connection", - :filter => search_filter, - :base => search_base, - :scope => scope, - :limit => sizelimit, - :sort => sort_control, - :referrals => return_referrals, - :deref => deref, - :attributes => search_attributes do |payload| - loop do - # should collect this into a private helper to clarify the structure - query_limit = 0 - if sizelimit > 0 - if paged_searches_supported - query_limit = (((sizelimit - n_results) < 126) ? (sizelimit - - n_results) : 0) - else - query_limit = sizelimit - end - end - - request = [ - search_base.to_ber, - scope.to_ber_enumerated, - deref.to_ber_enumerated, - query_limit.to_ber, # size limit - 0.to_ber, - attributes_only.to_ber, - search_filter.to_ber, - search_attributes.to_ber_sequence - ].to_ber_appsequence(3) - - # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory - # this breaks when calling to_ber. (Can't force binary data to UTF-8) - # we have to disable paging (even though server supports it) to get around this... - - controls = [] - controls << - [ - Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber, - # Criticality MUST be false to interoperate with normal LDAPs. - false.to_ber, - rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber - ].to_ber_sequence if paged_searches_supported - controls << sort_control if sort_control - controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) - - pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - write pkt - - result_pdu = nil - controls = [] - - while (be = read) && (pdu = Net::LDAP::PDU.new(be)) - case pdu.app_tag - when Net::LDAP::PDU::SearchReturnedData - n_results += 1 - yield pdu.search_entry if block_given? - when Net::LDAP::PDU::SearchResultReferral - if return_referrals - if block_given? - se = Net::LDAP::Entry.new - se[:search_referrals] = (pdu.search_referrals || []) - yield se - end - end - when Net::LDAP::PDU::SearchResult - result_pdu = pdu - controls = pdu.result_controls - if return_referrals && pdu.result_code == 10 - if block_given? - se = Net::LDAP::Entry.new - se[:search_referrals] = (pdu.search_referrals || []) - yield se - end - end - break - else - raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" - end - end - - # count number of pages of results - payload[:page_count] ||= 0 - payload[:page_count] += 1 - - # When we get here, we have seen a type-5 response. If there is no - # error AND there is an RFC-2696 cookie, then query again for the next - # page of results. If not, we're done. Don't screw this up or we'll - # break every search we do. - # - # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't - # that have a parameter of AsnSyntax? Does this just accidentally - # work? According to RFC-2696, the value expected in this position is - # of type OCTET STRING, covered in the default syntax supported by - # read_ber, so I guess we're ok. - more_pages = false - if result_pdu.result_code == 0 and controls - controls.each do |c| - if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS - # just in case some bogus server sends us more than 1 of these. - more_pages = false - if c.value and c.value.length > 0 - cookie = c.value.read_ber[1] - if cookie and cookie.length > 0 - rfc2696_cookie[1] = cookie - more_pages = true - end - end - end - end - end - - break unless more_pages - end # loop - - # track total result count - payload[:result_count] = n_results - - result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") - end # instrument - end - - MODIFY_OPERATIONS = { #:nodoc: - :add => 0, - :delete => 1, - :replace => 2 - } - - def self.modify_ops(operations) - ops = [] - if operations - operations.each { |op, attrib, values| - # TODO, fix the following line, which gives a bogus error if the - # opcode is invalid. - op_ber = MODIFY_OPERATIONS[op.to_sym].to_ber_enumerated - values = [ values ].flatten.map { |v| v.to_ber if v }.to_ber_set - values = [ attrib.to_s.to_ber, values ].to_ber_sequence - ops << [ op_ber, values ].to_ber - } - end - ops - end - - #-- - # TODO: need to support a time limit, in case the server fails to respond. - # TODO: We're throwing an exception here on empty DN. Should return a - # proper error instead, probaby from farther up the chain. - # TODO: If the user specifies a bogus opcode, we'll throw a confusing - # error here ("to_ber_enumerated is not defined on nil"). - #++ - 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(6) - pkt = [ next_msgid.to_ber, request ].to_ber_sequence - write pkt - - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" - - pdu - end - - #-- - # TODO: need to support a time limit, in case the server fails to respond. - # Unlike other operation-methods in this class, we return a result hash - # rather than a simple result number. This is experimental, and eventually - # we'll want to do this with all the others. The point is to have access - # to the error message and the matched-DN returned by the server. - #++ - def add(args) - add_dn = args[:dn] or raise Net::LDAP::LdapError, "Unable to add empty DN" - add_attrs = [] - a = args[:attributes] and a.each { |k, v| - 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) - pkt = [next_msgid.to_ber, request].to_ber_sequence - write pkt - - (be = read) && - (pdu = Net::LDAP::PDU.new(be)) && - (pdu.app_tag == Net::LDAP::PDU::AddResponse) or - raise Net::LDAP::LdapError, "response missing or invalid" - - pdu - end - - #-- - # TODO: need to support a time limit, in case the server fails to respond. - #++ - def rename(args) - old_dn = args[:olddn] or raise "Unable to rename empty DN" - new_rdn = args[:newrdn] or raise "Unable to rename to empty RDN" - 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 - - pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence - write pkt - - (be = read) && - (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or - raise Net::LDAP::LdapError.new( "response missing or invalid" ) - - pdu - end - - #-- - # TODO, need to support a time limit, in case the server fails to respond. - #++ - 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(10) - pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - write pkt - - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" - - pdu - end -end # class Connection diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb new file mode 100644 index 00000000..00d21502 --- /dev/null +++ b/lib/net/ldap/connection.rb @@ -0,0 +1,573 @@ +# This is a private class used internally by the library. It should not +# be called by user code. +class Net::LDAP::Connection #:nodoc: + include Net::LDAP::Instrumentation + + LdapVersion = 3 + MaxSaslChallenges = 10 + + def initialize(server) + @instrumentation_service = server[:instrumentation_service] + + begin + @conn = TCPSocket.new(server[:host], server[:port]) + rescue SocketError + raise Net::LDAP::LdapError, "No such address or other socket error." + rescue Errno::ECONNREFUSED + raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." + end + + if server[:encryption] + setup_encryption server[:encryption] + end + + yield self if block_given? + end + + module GetbyteForSSLSocket + def getbyte + getc.ord + end + end + + module FixSSLSocketSyncClose + def close + super + io.close + end + end + + def self.wrap_with_ssl(io) + raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL + ctx = OpenSSL::SSL::SSLContext.new + conn = OpenSSL::SSL::SSLSocket.new(io, ctx) + conn.connect + + # Doesn't work: + # conn.sync_close = true + + conn.extend(GetbyteForSSLSocket) unless conn.respond_to?(:getbyte) + conn.extend(FixSSLSocketSyncClose) + + conn + end + + #-- + # Helper method called only from new, and only after we have a + # successfully-opened @conn instance variable, which is a TCP connection. + # Depending on the received arguments, we establish SSL, potentially + # replacing the value of @conn accordingly. Don't generate any errors here + # if no encryption is requested. DO raise Net::LDAP::LdapError objects if encryption + # is requested and we have trouble setting it up. That includes if OpenSSL + # is not set up on the machine. (Question: how does the Ruby OpenSSL + # wrapper react in that case?) DO NOT filter exceptions raised by the + # OpenSSL library. Let them pass back to the user. That should make it + # easier for us to debug the problem reports. Presumably (hopefully?) that + # will also produce recognizable errors if someone tries to use this on a + # machine without OpenSSL. + # + # The simple_tls method is intended as the simplest, stupidest, easiest + # solution for people who want nothing more than encrypted comms with the + # LDAP server. It doesn't do any server-cert validation and requires + # nothing in the way of key files and root-cert files, etc etc. OBSERVE: + # WE REPLACE the value of @conn, which is presumed to be a connected + # TCPSocket object. + # + # The start_tls method is supported by many servers over the standard LDAP + # port. It does not require an alternative port for encrypted + # communications, as with simple_tls. Thanks for Kouhei Sutou for + # generously contributing the :start_tls path. + #++ + def setup_encryption(args) + case args[:method] + when :simple_tls + @conn = self.class.wrap_with_ssl(@conn) + # additional branches requiring server validation and peer certs, etc. + # go here. + when :start_tls + msgid = next_msgid.to_ber + request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + request_pkt = [msgid, request].to_ber_sequence + write request_pkt + be = read + raise Net::LDAP::LdapError, "no start_tls result" if be.nil? + pdu = Net::LDAP::PDU.new(be) + raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? + if pdu.result_code.zero? + @conn = self.class.wrap_with_ssl(@conn) + else + raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" + end + else + raise Net::LDAP::LdapError, "unsupported encryption method #{args[:method]}" + end + end + + #-- + # This is provided as a convenience method to make sure a connection + # object gets closed without waiting for a GC to happen. Clients shouldn't + # have to call it, but perhaps it will come in handy someday. + #++ + def close + @conn.close + @conn = nil + end + + # Internal: Reads and parses data from the configured connection. + # + # - syntax: the BER syntax to use to parse the read data with + # + # Returns basic BER objects. + def read(syntax = Net::LDAP::AsnSyntax) + instrument "read.net_ldap_connection", :syntax => syntax do |payload| + @conn.read_ber(syntax) do |id, content_length| + payload[:object_type_id] = id + payload[:content_length] = content_length + end + end + end + private :read + + # Internal: Writes the given packet to the configured connection. + # + # - packet: the BER data packet to write on the socket. + # + # Returns the return value from writing to the connection, which in some + # cases is the Integer number of bytes written to the socket. + def write(packet) + instrument "write.net_ldap_connection" do |payload| + payload[:content_length] = @conn.write(packet) + end + end + private :write + + def next_msgid + @msgid ||= 0 + @msgid += 1 + end + + def bind(auth) + instrument "bind.net_ldap_connection" do |payload| + payload[:method] = meth = auth[:method] + if [:simple, :anonymous, :anon].include?(meth) + bind_simple auth + elsif meth == :sasl + bind_sasl(auth) + elsif meth == :gss_spnego + bind_gss_spnego(auth) + else + raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" + end + end + end + + #-- + # Implements a simple user/psw authentication. Accessed by calling #bind + # with a method of :simple or :anonymous. + #++ + def bind_simple(auth) + user, psw = if auth[:method] == :simple + [auth[:username] || auth[:dn], auth[:password]] + else + ["", ""] + end + + raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + + msgid = next_msgid.to_ber + request = [LdapVersion.to_ber, user.to_ber, + psw.to_ber_contextspecific(0)].to_ber_appsequence(0) + request_pkt = [msgid, request].to_ber_sequence + write request_pkt + + (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + + pdu + end + + #-- + # Required parameters: :mechanism, :initial_credential and + # :challenge_response + # + # Mechanism is a string value that will be passed in the SASL-packet's + # "mechanism" field. + # + # Initial credential is most likely a string. It's passed in the initial + # BindRequest that goes to the server. In some protocols, it may be empty. + # + # Challenge-response is a Ruby proc that takes a single parameter and + # returns an object that will typically be a string. The + # challenge-response block is called when the server returns a + # BindResponse with a result code of 14 (saslBindInProgress). The + # challenge-response block receives a parameter containing the data + # returned by the server in the saslServerCreds field of the LDAP + # BindResponse packet. The challenge-response block may be called multiple + # times during the course of a SASL authentication, and each time it must + # return a value that will be passed back to the server as the credential + # data in the next BindRequest packet. + #++ + def bind_sasl(auth) + mech, cred, chall = auth[:mechanism], auth[:initial_credential], + auth[:challenge_response] + raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall) + + n = 0 + loop { + msgid = next_msgid.to_ber + sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) + request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) + request_pkt = [msgid, request].to_ber_sequence + write request_pkt + + (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + return pdu unless pdu.result_code == 14 # saslBindInProgress + raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + + cred = chall.call(pdu.result_server_sasl_creds) + } + + raise Net::LDAP::LdapError, "why are we here?" + end + private :bind_sasl + + #-- + # PROVISIONAL, only for testing SASL implementations. DON'T USE THIS YET. + # Uses Kohei Kajimoto's Ruby/NTLM. We have to find a clean way to + # integrate it without introducing an external dependency. + # + # This authentication method is accessed by calling #bind with a :method + # parameter of :gss_spnego. It requires :username and :password + # attributes, just like the :simple authentication method. It performs a + # GSS-SPNEGO authentication with the server, which is presumed to be a + # Microsoft Active Directory. + #++ + def bind_gss_spnego(auth) + require 'ntlm' + + user, psw = [auth[:username] || auth[:dn], auth[:password]] + raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + + nego = proc { |challenge| + t2_msg = NTLM::Message.parse(challenge) + t3_msg = t2_msg.response({ :user => user, :password => psw }, + { :ntlmv2 => true }) + t3_msg.serialize + } + + bind_sasl(:method => :sasl, :mechanism => "GSS-SPNEGO", + :initial_credential => NTLM::Message::Type1.new.serialize, + :challenge_response => nego) + end + private :bind_gss_spnego + + + #-- + # Allow the caller to specify a sort control + # + # The format of the sort control needs to be: + # + # :sort_control => ["cn"] # just a string + # or + # :sort_control => [["cn", "matchingRule", true]] #attribute, matchingRule, direction (true / false) + # or + # :sort_control => ["givenname","sn"] #multiple strings or arrays + # + def encode_sort_controls(sort_definitions) + return sort_definitions unless sort_definitions + + sort_control_values = sort_definitions.map do |control| + control = Array(control) # if there is only an attribute name as a string then infer the orderinrule and reverseorder + control[0] = String(control[0]).to_ber, + control[1] = String(control[1]).to_ber, + control[2] = (control[2] == true).to_ber + control.to_ber_sequence + end + sort_control = [ + Net::LDAP::LDAPControls::SORT_REQUEST.to_ber, + false.to_ber, + sort_control_values.to_ber_sequence.to_s.to_ber + ].to_ber_sequence + end + + #-- + # Alternate implementation, this yields each search entry to the caller as + # it are received. + # + # TODO: certain search parameters are hardcoded. + # TODO: if we mis-parse the server results or the results are wrong, we + # can block forever. That's because we keep reading results until we get a + # type-5 packet, which might never come. We need to support the time-limit + # in the protocol. + #++ + def search(args = {}) + search_filter = (args && args[:filter]) || + Net::LDAP::Filter.eq("objectclass", "*") + search_filter = Net::LDAP::Filter.construct(search_filter) if search_filter.is_a?(String) + search_base = (args && args[:base]) || "dc=example, dc=com" + search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber} + return_referrals = args && args[:return_referrals] == true + sizelimit = (args && args[:size].to_i) || 0 + raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0 + paged_searches_supported = (args && args[:paged_searches_supported]) + + attributes_only = (args and args[:attributes_only] == true) + scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree + raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + + sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) + + deref = args[:deref] || Net::LDAP::DerefAliases_Never + raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) + + + # An interesting value for the size limit would be close to A/D's + # built-in page limit of 1000 records, but openLDAP newer than version + # 2.2.0 chokes on anything bigger than 126. You get a silent error that + # is easily visible by running slapd in debug mode. Go figure. + # + # Changed this around 06Sep06 to support a caller-specified search-size + # limit. Because we ALWAYS do paged searches, we have to work around the + # problem that it's not legal to specify a "normal" sizelimit (in the + # body of the search request) that is larger than the page size we're + # requesting. Unfortunately, I have the feeling that this will break + # with LDAP servers that don't support paged searches!!! + # + # (Because we pass zero as the sizelimit on search rounds when the + # remaining limit is larger than our max page size of 126. In these + # cases, I think the caller's search limit will be ignored!) + # + # CONFIRMED: This code doesn't work on LDAPs that don't support paged + # searches when the size limit is larger than 126. We're going to have + # to do a root-DSE record search and not do a paged search if the LDAP + # doesn't support it. Yuck. + rfc2696_cookie = [126, ""] + result_pdu = nil + n_results = 0 + + instrument "search.net_ldap_connection", + :filter => search_filter, + :base => search_base, + :scope => scope, + :limit => sizelimit, + :sort => sort_control, + :referrals => return_referrals, + :deref => deref, + :attributes => search_attributes do |payload| + loop do + # should collect this into a private helper to clarify the structure + query_limit = 0 + if sizelimit > 0 + if paged_searches_supported + query_limit = (((sizelimit - n_results) < 126) ? (sizelimit - + n_results) : 0) + else + query_limit = sizelimit + end + end + + request = [ + search_base.to_ber, + scope.to_ber_enumerated, + deref.to_ber_enumerated, + query_limit.to_ber, # size limit + 0.to_ber, + attributes_only.to_ber, + search_filter.to_ber, + search_attributes.to_ber_sequence + ].to_ber_appsequence(3) + + # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory + # this breaks when calling to_ber. (Can't force binary data to UTF-8) + # we have to disable paging (even though server supports it) to get around this... + + controls = [] + controls << + [ + Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber, + # Criticality MUST be false to interoperate with normal LDAPs. + false.to_ber, + rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber + ].to_ber_sequence if paged_searches_supported + controls << sort_control if sort_control + controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) + + pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence + write pkt + + result_pdu = nil + controls = [] + + while (be = read) && (pdu = Net::LDAP::PDU.new(be)) + case pdu.app_tag + when Net::LDAP::PDU::SearchReturnedData + n_results += 1 + yield pdu.search_entry if block_given? + when Net::LDAP::PDU::SearchResultReferral + if return_referrals + if block_given? + se = Net::LDAP::Entry.new + se[:search_referrals] = (pdu.search_referrals || []) + yield se + end + end + when Net::LDAP::PDU::SearchResult + result_pdu = pdu + controls = pdu.result_controls + if return_referrals && pdu.result_code == 10 + if block_given? + se = Net::LDAP::Entry.new + se[:search_referrals] = (pdu.search_referrals || []) + yield se + end + end + break + else + raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" + end + end + + # count number of pages of results + payload[:page_count] ||= 0 + payload[:page_count] += 1 + + # When we get here, we have seen a type-5 response. If there is no + # error AND there is an RFC-2696 cookie, then query again for the next + # page of results. If not, we're done. Don't screw this up or we'll + # break every search we do. + # + # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't + # that have a parameter of AsnSyntax? Does this just accidentally + # work? According to RFC-2696, the value expected in this position is + # of type OCTET STRING, covered in the default syntax supported by + # read_ber, so I guess we're ok. + more_pages = false + if result_pdu.result_code == 0 and controls + controls.each do |c| + if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS + # just in case some bogus server sends us more than 1 of these. + more_pages = false + if c.value and c.value.length > 0 + cookie = c.value.read_ber[1] + if cookie and cookie.length > 0 + rfc2696_cookie[1] = cookie + more_pages = true + end + end + end + end + end + + break unless more_pages + end # loop + + # track total result count + payload[:result_count] = n_results + + result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") + end # instrument + end + + MODIFY_OPERATIONS = { #:nodoc: + :add => 0, + :delete => 1, + :replace => 2 + } + + def self.modify_ops(operations) + ops = [] + if operations + operations.each { |op, attrib, values| + # TODO, fix the following line, which gives a bogus error if the + # opcode is invalid. + op_ber = MODIFY_OPERATIONS[op.to_sym].to_ber_enumerated + values = [ values ].flatten.map { |v| v.to_ber if v }.to_ber_set + values = [ attrib.to_s.to_ber, values ].to_ber_sequence + ops << [ op_ber, values ].to_ber + } + end + ops + end + + #-- + # TODO: need to support a time limit, in case the server fails to respond. + # TODO: We're throwing an exception here on empty DN. Should return a + # proper error instead, probaby from farther up the chain. + # TODO: If the user specifies a bogus opcode, we'll throw a confusing + # error here ("to_ber_enumerated is not defined on nil"). + #++ + 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(6) + pkt = [ next_msgid.to_ber, request ].to_ber_sequence + write pkt + + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + + pdu + end + + #-- + # TODO: need to support a time limit, in case the server fails to respond. + # Unlike other operation-methods in this class, we return a result hash + # rather than a simple result number. This is experimental, and eventually + # we'll want to do this with all the others. The point is to have access + # to the error message and the matched-DN returned by the server. + #++ + def add(args) + add_dn = args[:dn] or raise Net::LDAP::LdapError, "Unable to add empty DN" + add_attrs = [] + a = args[:attributes] and a.each { |k, v| + 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) + pkt = [next_msgid.to_ber, request].to_ber_sequence + write pkt + + (be = read) && + (pdu = Net::LDAP::PDU.new(be)) && + (pdu.app_tag == Net::LDAP::PDU::AddResponse) or + raise Net::LDAP::LdapError, "response missing or invalid" + + pdu + end + + #-- + # TODO: need to support a time limit, in case the server fails to respond. + #++ + def rename(args) + old_dn = args[:olddn] or raise "Unable to rename empty DN" + new_rdn = args[:newrdn] or raise "Unable to rename to empty RDN" + 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 + + pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence + write pkt + + (be = read) && + (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or + raise Net::LDAP::LdapError.new( "response missing or invalid" ) + + pdu + end + + #-- + # TODO, need to support a time limit, in case the server fails to respond. + #++ + 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(10) + pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence + write pkt + + (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + + pdu + end +end # class Connection From 23deefde7d558d04706b2d5fbf11fdeca77fffe0 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sun, 5 Oct 2014 17:26:57 -0700 Subject: [PATCH 098/435] implement search timeout --- lib/net/ldap.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 5effe57a..e03fd4dd 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -609,6 +609,7 @@ def open # Net::LDAP::SearchScope_WholeSubtree. Default is WholeSubtree.) # * :size (an integer indicating the maximum number of search entries to # return. Default is zero, which signifies no limit.) + # * :time (an integer restricting the maximum time in seconds allowed for a search RFC 4511 4.5.1.5) # * :deref (one of: Net::LDAP::DerefAliases_Never, Net::LDAP::DerefAliases_Search, # Net::LDAP::DerefAliases_Find, Net::LDAP::DerefAliases_Always. Default is Never.) # @@ -1485,6 +1486,7 @@ def search(args = {}) search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber} return_referrals = args && args[:return_referrals] == true sizelimit = (args && args[:size].to_i) || 0 + timelimit = (args && args[:time].to_i) || 0 raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0 paged_searches_supported = (args && args[:paged_searches_supported]) @@ -1548,7 +1550,7 @@ def search(args = {}) scope.to_ber_enumerated, deref.to_ber_enumerated, query_limit.to_ber, # size limit - 0.to_ber, + timelimit.to_ber, attributes_only.to_ber, search_filter.to_ber, search_attributes.to_ber_sequence From 8048c5d25d23030ae3825f68bf28d10a41e41d9f Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sun, 5 Oct 2014 17:27:08 -0700 Subject: [PATCH 099/435] add timelimit to instrumentation --- lib/net/ldap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index e03fd4dd..dc395a5b 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1529,6 +1529,7 @@ def search(args = {}) :base => search_base, :scope => scope, :limit => sizelimit, + :timelimit => timelimit, :sort => sort_control, :referrals => return_referrals, :deref => deref, From 3c2c5e63589e26ffe3804cb6cd588bc268d20547 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Sun, 5 Oct 2014 17:33:08 -0700 Subject: [PATCH 100/435] document the default --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index dc395a5b..0a2625ed 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -609,7 +609,7 @@ def open # Net::LDAP::SearchScope_WholeSubtree. Default is WholeSubtree.) # * :size (an integer indicating the maximum number of search entries to # return. Default is zero, which signifies no limit.) - # * :time (an integer restricting the maximum time in seconds allowed for a search RFC 4511 4.5.1.5) + # * :time (an integer restricting the maximum time in seconds allowed for a search. Default is zero, no time limit RFC 4511 4.5.1.5) # * :deref (one of: Net::LDAP::DerefAliases_Never, Net::LDAP::DerefAliases_Search, # Net::LDAP::DerefAliases_Find, Net::LDAP::DerefAliases_Always. Default is Never.) # From e8e660222e6ed25ea2c9e733b4395a575df74b12 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 14:55:31 -0700 Subject: [PATCH 101/435] require minitest/mock --- test/common.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/common.rb b/test/common.rb index baa06884..e352a8f1 100644 --- a/test/common.rb +++ b/test/common.rb @@ -1,3 +1,4 @@ # Add 'lib' to load path. require 'test/unit' +require 'minitest/mock' require 'net/ldap' From d8f9f3714b2d3ee0f4efdfbd94d45aeaa265f1ad Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 14:56:08 -0700 Subject: [PATCH 102/435] dependency inject :socket allows us to mock out the actual connection for testing --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 00d21502..1d86d809 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -10,7 +10,7 @@ def initialize(server) @instrumentation_service = server[:instrumentation_service] begin - @conn = TCPSocket.new(server[:host], server[:port]) + @conn = server[:socket] || TCPSocket.new(server[:host], server[:port]) rescue SocketError raise Net::LDAP::LdapError, "No such address or other socket error." rescue Errno::ECONNREFUSED From d318ff4101adaebc5fbcb93e9a083d2fdb55ac3d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 14:57:21 -0700 Subject: [PATCH 103/435] add Connection#write_request higher level abstraction to make testing easier and to DRY up existing socket IO --- lib/net/ldap/connection.rb | 6 ++++++ test/test_ldap_connection.rb | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 1d86d809..e3b24d7d 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -141,6 +141,12 @@ def write(packet) end private :write + # Internal: Convert `request` and `controls` to a BER data packet with the + # next message id and call `#write` on it. + def write_request(request, controls = nil) + write([next_msgid, request, controls].compact.to_ber_sequence) + end + def next_msgid @msgid ||= 0 @msgid += 1 diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index a3643016..30d0979e 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -21,4 +21,27 @@ def test_modify_ops_replace expected = [ "0#\n\x01\x020\x1E\x04\x04mail1\x16\x04\x14testuser@example.com" ] assert_equal(expected, result) end + + def test_write_request + mock = Minitest::Mock.new + mock.expect(:write, true, [[1, "request"].to_ber_sequence]) + conn = Net::LDAP::Connection.new(:socket => mock) + conn.write_request("request") + end + + def test_write_request_with_controls + mock = Minitest::Mock.new + mock.expect(:write, true, [[1, "request", "controls"].to_ber_sequence]) + conn = Net::LDAP::Connection.new(:socket => mock) + conn.write_request("request", "controls") + end + + def test_write_request_increments_msgid + mock = Minitest::Mock.new + mock.expect(:write, true, [[1, "request1"].to_ber_sequence]) + mock.expect(:write, true, [[2, "request2"].to_ber_sequence]) + conn = Net::LDAP::Connection.new(:socket => mock) + conn.write_request("request1") + conn.write_request("request2") + end end From 262819ae9056125a51f788600468680a3f0dd56d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 15:01:35 -0700 Subject: [PATCH 104/435] ber formatted next_msgid --- lib/net/ldap/connection.rb | 6 +++--- test/test_ldap_connection.rb | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e3b24d7d..1afc1e2b 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -141,10 +141,10 @@ def write(packet) end private :write - # Internal: Convert `request` and `controls` to a BER data packet with the - # next message id and call `#write` on it. + # Internal: Convert BER formatted `request` and `controls` to a BER data + # packet with the next message id (`#next_msgid`) and call `#write` on it. def write_request(request, controls = nil) - write([next_msgid, request, controls].compact.to_ber_sequence) + write([next_msgid.to_ber, request, controls].compact.to_ber_sequence) end def next_msgid diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 30d0979e..d4f5d763 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -24,22 +24,22 @@ def test_modify_ops_replace def test_write_request mock = Minitest::Mock.new - mock.expect(:write, true, [[1, "request"].to_ber_sequence]) + mock.expect(:write, true, [[1.to_ber, "request"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) conn.write_request("request") end def test_write_request_with_controls mock = Minitest::Mock.new - mock.expect(:write, true, [[1, "request", "controls"].to_ber_sequence]) + mock.expect(:write, true, [[1.to_ber, "request", "controls"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) conn.write_request("request", "controls") end def test_write_request_increments_msgid mock = Minitest::Mock.new - mock.expect(:write, true, [[1, "request1"].to_ber_sequence]) - mock.expect(:write, true, [[2, "request2"].to_ber_sequence]) + mock.expect(:write, true, [[1.to_ber, "request1"].to_ber_sequence]) + mock.expect(:write, true, [[2.to_ber, "request2"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) conn.write_request("request1") conn.write_request("request2") From f52425dad68593371b8613512fe70edd1a346442 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 15:01:55 -0700 Subject: [PATCH 105/435] make #write_request private --- lib/net/ldap/connection.rb | 1 + test/test_ldap_connection.rb | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 1afc1e2b..4b26a1ba 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -146,6 +146,7 @@ def write(packet) def write_request(request, controls = nil) write([next_msgid.to_ber, request, controls].compact.to_ber_sequence) end + private :write_request def next_msgid @msgid ||= 0 diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index d4f5d763..055f17e2 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -26,14 +26,14 @@ def test_write_request mock = Minitest::Mock.new mock.expect(:write, true, [[1.to_ber, "request"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.write_request("request") + conn.send(:write_request, "request") end def test_write_request_with_controls mock = Minitest::Mock.new mock.expect(:write, true, [[1.to_ber, "request", "controls"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.write_request("request", "controls") + conn.send(:write_request, "request", "controls") end def test_write_request_increments_msgid @@ -41,7 +41,7 @@ def test_write_request_increments_msgid mock.expect(:write, true, [[1.to_ber, "request1"].to_ber_sequence]) mock.expect(:write, true, [[2.to_ber, "request2"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.write_request("request1") - conn.write_request("request2") + conn.send(:write_request, "request1") + conn.send(:write_request, "request2") end end From f1b53e796219dfbf1b9090a118116a5ef034a6e3 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 6 Oct 2014 15:08:12 -0700 Subject: [PATCH 106/435] DRY up #write calls with #write_request --- lib/net/ldap/connection.rb | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4b26a1ba..63e31fed 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -85,10 +85,8 @@ def setup_encryption(args) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls - msgid = next_msgid.to_ber request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt + write_request(request) be = read raise Net::LDAP::LdapError, "no start_tls result" if be.nil? pdu = Net::LDAP::PDU.new(be) @@ -181,11 +179,9 @@ def bind_simple(auth) raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) - msgid = next_msgid.to_ber request = [LdapVersion.to_ber, user.to_ber, psw.to_ber_contextspecific(0)].to_ber_appsequence(0) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt + write_request(request) (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" @@ -220,11 +216,9 @@ def bind_sasl(auth) n = 0 loop { - msgid = next_msgid.to_ber sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) - request_pkt = [msgid, request].to_ber_sequence - write request_pkt + write_request(request) (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" return pdu unless pdu.result_code == 14 # saslBindInProgress @@ -398,8 +392,7 @@ def search(args = {}) controls << sort_control if sort_control controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) - pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - write pkt + write_request(request, controls) result_pdu = nil controls = [] @@ -507,8 +500,7 @@ def modify(args) ops = self.class.modify_ops args[:operations] request = [ modify_dn.to_ber, ops.to_ber_sequence ].to_ber_appsequence(6) - pkt = [ next_msgid.to_ber, request ].to_ber_sequence - write pkt + write_request(request) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" @@ -530,8 +522,7 @@ def add(args) } request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8) - pkt = [next_msgid.to_ber, request].to_ber_sequence - write pkt + write_request(request) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && @@ -553,8 +544,7 @@ def rename(args) request = [old_dn.to_ber, new_rdn.to_ber, delete_attrs.to_ber] request << new_superior.to_ber_contextspecific(0) unless new_superior == nil - pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence - write pkt + write_request(request.to_ber_appsequence(12)) (be = read) && (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or @@ -570,8 +560,7 @@ 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(10) - pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence - write pkt + write_request(request, controls) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" From 7e3f4e7d33113bb7052509b2e4210dee35654744 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 7 Oct 2014 12:04:47 -0700 Subject: [PATCH 107/435] just use #write not adding another method call. Since it's a private method, not giving any deprecation warning. --- lib/net/ldap/connection.rb | 32 ++++++++++++++------------------ test/test_ldap_connection.rb | 14 +++++++------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 63e31fed..1e74464f 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -86,7 +86,7 @@ def setup_encryption(args) # go here. when :start_tls request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) - write_request(request) + write(request) be = read raise Net::LDAP::LdapError, "no start_tls result" if be.nil? pdu = Net::LDAP::PDU.new(be) @@ -126,26 +126,22 @@ def read(syntax = Net::LDAP::AsnSyntax) end private :read - # Internal: Writes the given packet to the configured connection. + # Internal: Write a BER formatted packet with the next message id to the + # configured connection. # - # - packet: the BER data packet to write on the socket. + # - request: required BER formatted request + # - controls: optional BER formatted controls # # Returns the return value from writing to the connection, which in some # cases is the Integer number of bytes written to the socket. - def write(packet) + def write(request, controls = nil) instrument "write.net_ldap_connection" do |payload| + packet = [next_msgid.to_ber, request, controls].compact.to_ber_sequence payload[:content_length] = @conn.write(packet) end end private :write - # Internal: Convert BER formatted `request` and `controls` to a BER data - # packet with the next message id (`#next_msgid`) and call `#write` on it. - def write_request(request, controls = nil) - write([next_msgid.to_ber, request, controls].compact.to_ber_sequence) - end - private :write_request - def next_msgid @msgid ||= 0 @msgid += 1 @@ -181,7 +177,7 @@ def bind_simple(auth) request = [LdapVersion.to_ber, user.to_ber, psw.to_ber_contextspecific(0)].to_ber_appsequence(0) - write_request(request) + write(request) (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" @@ -218,7 +214,7 @@ def bind_sasl(auth) loop { sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) - write_request(request) + write(request) (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" return pdu unless pdu.result_code == 14 # saslBindInProgress @@ -392,7 +388,7 @@ def search(args = {}) controls << sort_control if sort_control controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) - write_request(request, controls) + write(request, controls) result_pdu = nil controls = [] @@ -500,7 +496,7 @@ def modify(args) ops = self.class.modify_ops args[:operations] request = [ modify_dn.to_ber, ops.to_ber_sequence ].to_ber_appsequence(6) - write_request(request) + write(request) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" @@ -522,7 +518,7 @@ def add(args) } request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8) - write_request(request) + write(request) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && @@ -544,7 +540,7 @@ def rename(args) 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(request.to_ber_appsequence(12)) + write(request.to_ber_appsequence(12)) (be = read) && (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or @@ -560,7 +556,7 @@ 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(10) - write_request(request, controls) + write(request, controls) (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 055f17e2..2498ac8f 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -22,26 +22,26 @@ def test_modify_ops_replace assert_equal(expected, result) end - def test_write_request + def test_write mock = Minitest::Mock.new mock.expect(:write, true, [[1.to_ber, "request"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.send(:write_request, "request") + conn.send(:write, "request") end - def test_write_request_with_controls + def test_write_with_controls mock = Minitest::Mock.new mock.expect(:write, true, [[1.to_ber, "request", "controls"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.send(:write_request, "request", "controls") + conn.send(:write, "request", "controls") end - def test_write_request_increments_msgid + def test_write_increments_msgid mock = Minitest::Mock.new mock.expect(:write, true, [[1.to_ber, "request1"].to_ber_sequence]) mock.expect(:write, true, [[2.to_ber, "request2"].to_ber_sequence]) conn = Net::LDAP::Connection.new(:socket => mock) - conn.send(:write_request, "request1") - conn.send(:write_request, "request2") + conn.send(:write, "request1") + conn.send(:write, "request2") end end From 1b7bba99cc3d5e2908ffb3b20beb5f1d5fc59965 Mon Sep 17 00:00:00 2001 From: Christopher Warner Date: Mon, 28 Jul 2014 12:28:33 -0400 Subject: [PATCH 108/435] start_tls is now supported --- lib/net/ldap.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 8fb9107e..cbd7917c 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -486,9 +486,9 @@ def authenticate(username, password) # standard port for simple-TLS encrypted connections is 636. Be sure you # are using the correct port. # - # [Note: a future version of Net::LDAP will support the STARTTLS LDAP - # control, which will enable encrypted communications on the same TCP port - # used for unencrypted connections.] + # The :start_tls like the :simple_tls encryption method also encrypts all + # communcations with the LDAP server. With the exception that it operates + # over the standard TCP port. def encryption(args) case args when :simple_tls, :start_tls From 342806f218cb4abee7d1ea840d15ffdae0255bdd Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 9 Oct 2014 10:56:54 -0700 Subject: [PATCH 109/435] revive entry test --- test/test_entry.rb | 94 +++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/test/test_entry.rb b/test/test_entry.rb index 73898d67..ee067c61 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,59 +1,43 @@ require 'common' -=begin class TestEntry < Test::Unit::TestCase -Commented out until I can make it a spec. - context "An instance of Entry" do - setup do - @entry = Net::LDAP::Entry.new 'cn=Barbara,o=corp' - end - - should "be initialized with the DN" do - assert_equal 'cn=Barbara,o=corp', @entry.dn - end - - should 'return an empty array when accessing a nonexistent attribute (index lookup)' do - assert_equal [], @entry['sn'] - end - - should 'return an empty array when accessing a nonexistent attribute (method call)' do - assert_equal [], @entry.sn - end - - should 'create an attribute on assignment (index lookup)' do - @entry['sn'] = 'Jensen' - assert_equal ['Jensen'], @entry['sn'] - end - - should 'create an attribute on assignment (method call)' do - @entry.sn = 'Jensen' - assert_equal ['Jensen'], @entry.sn - end - - should 'have attributes accessible by index lookup' do - @entry['sn'] = 'Jensen' - assert_equal ['Jensen'], @entry['sn'] - end - - should 'have attributes accessible using a Symbol as the index' do - @entry[:sn] = 'Jensen' - assert_equal ['Jensen'], @entry[:sn] - end - - should 'have attributes accessible by method call' do - @entry['sn'] = 'Jensen' - assert_equal ['Jensen'], @entry.sn - end - - should 'ignore case of attribute names' do - @entry['sn'] = 'Jensen' - assert_equal ['Jensen'], @entry.sn - assert_equal ['Jensen'], @entry.Sn - assert_equal ['Jensen'], @entry.SN - assert_equal ['Jensen'], @entry['sn'] - assert_equal ['Jensen'], @entry['Sn'] - assert_equal ['Jensen'], @entry['SN'] - end - end + def setup + @entry = Net::LDAP::Entry.new 'cn=Barbara,o=corp' + end + + def test_dn + assert_equal 'cn=Barbara,o=corp', @entry.dn + end + + def test_empty_array_when_accessing_nonexistent_attribute + assert_equal [], @entry['sn'] + assert_equal [], @entry.sn + end + + def test_attribute_assignment + @entry['sn'] = 'Jensen' + assert_equal ['Jensen'], @entry['sn'] + assert_equal ['Jensen'], @entry.sn + assert_equal ['Jensen'], @entry[:sn] + + @entry[:sn] = 'Jensen' + assert_equal ['Jensen'], @entry['sn'] + assert_equal ['Jensen'], @entry.sn + assert_equal ['Jensen'], @entry[:sn] + + @entry.sn = 'Jensen' + assert_equal ['Jensen'], @entry['sn'] + assert_equal ['Jensen'], @entry.sn + assert_equal ['Jensen'], @entry[:sn] + end + + def test_case_insensitive_attribute_names + @entry['sn'] = 'Jensen' + assert_equal ['Jensen'], @entry.sn + assert_equal ['Jensen'], @entry.Sn + assert_equal ['Jensen'], @entry.SN + assert_equal ['Jensen'], @entry['sn'] + assert_equal ['Jensen'], @entry['Sn'] + assert_equal ['Jensen'], @entry['SN'] + end end -=end From 04ef43850ad42c23630494b249f4c33ebdbf102a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 9 Oct 2014 11:15:52 -0700 Subject: [PATCH 110/435] skip failing test --- test/test_entry.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_entry.rb b/test/test_entry.rb index ee067c61..c1d1739b 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -11,6 +11,11 @@ def test_dn def test_empty_array_when_accessing_nonexistent_attribute assert_equal [], @entry['sn'] + end + + def test_empty_attribute_by_method + skip "Net::LDAP::Entry#valid_attribute? requires an attribute to be defined first" + # What is the valid encoding for attribute names? assert_equal [], @entry.sn end From e520d62670949bfe2dea3b8902b7278527ef5cf2 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 9 Oct 2014 11:28:20 -0700 Subject: [PATCH 111/435] remove test until #117 --- test/test_entry.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/test_entry.rb b/test/test_entry.rb index c1d1739b..b270069f 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -13,12 +13,6 @@ def test_empty_array_when_accessing_nonexistent_attribute assert_equal [], @entry['sn'] end - def test_empty_attribute_by_method - skip "Net::LDAP::Entry#valid_attribute? requires an attribute to be defined first" - # What is the valid encoding for attribute names? - assert_equal [], @entry.sn - end - def test_attribute_assignment @entry['sn'] = 'Jensen' assert_equal ['Jensen'], @entry['sn'] From 5b224805c662e6c9da0fdab4bfae7638a006cc84 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 9 Oct 2014 16:22:18 -0700 Subject: [PATCH 112/435] translate spec/integration/ssl_ber_spec to minitest --- spec/integration/ssl_ber_spec.rb | 39 -------------------------------- test/common.rb | 1 + test/test_ssl_ber.rb | 37 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 39 deletions(-) delete mode 100644 spec/integration/ssl_ber_spec.rb create mode 100644 test/test_ssl_ber.rb diff --git a/spec/integration/ssl_ber_spec.rb b/spec/integration/ssl_ber_spec.rb deleted file mode 100644 index ae8900e3..00000000 --- a/spec/integration/ssl_ber_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'spec_helper' - -require 'net/ldap' -require 'timeout' - -describe "BER serialisation (SSL)" do - # Transmits str to #to and reads it back from #from. - # - def transmit(str) - Timeout::timeout(1) do - to.write(str) - to.close - - from.read - end - end - - attr_reader :to, :from - before(:each) do - @from, @to = IO.pipe - - # The production code operates on sockets, which do need #connect called - # on them to work. Pipes are more robust for this test, so we'll skip - # the #connect call since it fails. - flexmock(OpenSSL::SSL::SSLSocket). - new_instances.should_receive(:connect => nil) - - @to = Net::LDAP::Connection.wrap_with_ssl(to) - @from = Net::LDAP::Connection.wrap_with_ssl(from) - end - - it "should transmit strings" do - transmit('foo').should == 'foo' - end - it "should correctly transmit numbers" do - to.write 1234.to_ber - from.read_ber.should == 1234 - end -end \ No newline at end of file diff --git a/test/common.rb b/test/common.rb index baa06884..1ff8d12a 100644 --- a/test/common.rb +++ b/test/common.rb @@ -1,3 +1,4 @@ # Add 'lib' to load path. require 'test/unit' require 'net/ldap' +require 'flexmock/test_unit' diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb new file mode 100644 index 00000000..68b48d8c --- /dev/null +++ b/test/test_ssl_ber.rb @@ -0,0 +1,37 @@ +require 'common' +require 'timeout' + +class TestSSLBER < Test::Unit::TestCase + # Transmits str to @to and reads it back from @from. + # + def transmit(str) + Timeout::timeout(1) do + @to.write(str) + @to.close + + @from.read + end + end + + def setup + @from, @to = IO.pipe + + # The production code operates on sockets, which do need #connect called + # on them to work. Pipes are more robust for this test, so we'll skip + # the #connect call since it fails. + flexmock(OpenSSL::SSL::SSLSocket). + new_instances.should_receive(:connect => nil) + + @to = Net::LDAP::Connection.wrap_with_ssl(@to) + @from = Net::LDAP::Connection.wrap_with_ssl(@from) + end + + def test_transmit_strings + assert_equal "foo", transmit("foo") + end + + def test_transmit_ber_encoded_numbers + @to.write 1234.to_ber + assert_equal 1234, @from.read_ber + end +end From 2d406e8bfe5ea6d82b0841401d81bb50ea36386c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 9 Oct 2014 16:23:59 -0700 Subject: [PATCH 113/435] move spec/ber over to test/ --- {spec/unit => test}/ber/ber_spec.rb | 24 +++++++++---------- .../unit => test}/ber/core_ext/array_spec.rb | 0 .../unit => test}/ber/core_ext/string_spec.rb | 14 +++++------ 3 files changed, 19 insertions(+), 19 deletions(-) rename {spec/unit => test}/ber/ber_spec.rb (96%) rename {spec/unit => test}/ber/core_ext/array_spec.rb (100%) rename {spec/unit => test}/ber/core_ext/string_spec.rb (91%) diff --git a/spec/unit/ber/ber_spec.rb b/test/ber/ber_spec.rb similarity index 96% rename from spec/unit/ber/ber_spec.rb rename to test/ber/ber_spec.rb index 68242c43..45e134a4 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/test/ber/ber_spec.rb @@ -4,23 +4,23 @@ require 'net/ldap' describe "BER encoding of" do - - RSpec::Matchers.define :properly_encode_and_decode do + + RSpec::Matchers.define :properly_encode_and_decode do match do |given| given.to_ber.read_ber.should == given end end - + context "arrays" do it "should properly encode/decode []" do [].should properly_encode_and_decode - end + end it "should properly encode/decode [1,2,3]" do ary = [1,2,3] encoded_ary = ary.map { |el| el.to_ber }.to_ber - + encoded_ary.read_ber.should == ary - end + end end context "booleans" do it "should encode true" do @@ -62,17 +62,17 @@ it "should correctly handle powers of two" do 100.times do |p| n = 2 << p - + n.should properly_encode_and_decode end - end + end it "should correctly handle powers of ten" do 100.times do |p| n = 5 * 10**p - + n.should properly_encode_and_decode end - end + end end end if "Ruby 1.9".respond_to?(:encoding) @@ -86,7 +86,7 @@ end it "should properly encode binary data strings using to_ber_bin" do # This is used for searching for GUIDs in Active Directory - ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == + ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") end it "should not fail on strings that can not be converted to UTF-8" do @@ -108,7 +108,7 @@ "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus". read_ber(Net::LDAP::AsnSyntax).should == [1, [3, "Administrator", "ad_is_bogus"]] - end + end end end diff --git a/spec/unit/ber/core_ext/array_spec.rb b/test/ber/core_ext/array_spec.rb similarity index 100% rename from spec/unit/ber/core_ext/array_spec.rb rename to test/ber/core_ext/array_spec.rb diff --git a/spec/unit/ber/core_ext/string_spec.rb b/test/ber/core_ext/string_spec.rb similarity index 91% rename from spec/unit/ber/core_ext/string_spec.rb rename to test/ber/core_ext/string_spec.rb index ef2c4981..edcd4403 100644 --- a/spec/unit/ber/core_ext/string_spec.rb +++ b/test/ber/core_ext/string_spec.rb @@ -9,10 +9,10 @@ @str = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED") @result = str.read_ber!(Net::LDAP::AsnSyntax) end - + it "should correctly parse the ber message" do result.should == [1, [3, "Administrator", "ad_is_bogus"]] - end + end it "should leave unconsumed part of message in place" do str.should == " UNCONSUMED" end @@ -21,9 +21,9 @@ attr_reader :initial_value before(:each) do stub_exception_class = Class.new(StandardError) - + @initial_value = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus") - @str = initial_value.dup + @str = initial_value.dup # Defines a string io = StringIO.new(initial_value) @@ -32,16 +32,16 @@ raise stub_exception_class end flexmock(StringIO).should_receive(:new).and_return(io) - + begin - str.read_ber!(Net::LDAP::AsnSyntax) + str.read_ber!(Net::LDAP::AsnSyntax) rescue stub_exception_class # EMPTY ON PURPOSE else raise "The stub code should raise an exception!" end end - + it "should not modify string" do str.should == initial_value end From eaca23831966f9cf454037b43d3b10aae177a50d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 9 Oct 2014 19:02:45 -0700 Subject: [PATCH 114/435] Run tests and specs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6877e706..65d9ad5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,4 @@ rvm: matrix: allow_failures: - rvm: jruby-19mode -script: bundle exec rake spec +script: bundle exec rake From 73cfd7903b95bff4b74a93c5382627a2826c9859 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 9 Oct 2014 19:10:11 -0700 Subject: [PATCH 115/435] Add Ruby 2.1.2 to the build matrix --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 65d9ad5a..3202880c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: ruby rvm: - 1.9.3 - 2.0.0 + - 2.1.2 - jruby-19mode - rbx-19mode matrix: From cc60637e4138e0dd2648dc64d613efcdd1624579 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 9 Oct 2014 19:17:34 -0700 Subject: [PATCH 116/435] Add Rubinius 2.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3202880c..dcd29b95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ rvm: - 2.1.2 - jruby-19mode - rbx-19mode + - rbx-2 matrix: allow_failures: - rvm: jruby-19mode From a3668e3a14eadd521f3d5c4db70eda41ebc7577c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 9 Oct 2014 19:19:58 -0700 Subject: [PATCH 117/435] :fire: spec/spec.opts from gemspec files, manifest --- Manifest.txt | 1 - net-ldap.gemspec | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Manifest.txt b/Manifest.txt index bea51c0c..9c81b63c 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -32,7 +32,6 @@ lib/net/ldap/version.rb lib/net/snmp.rb net-ldap.gemspec spec/integration/ssl_ber_spec.rb -spec/spec.opts spec/spec_helper.rb spec/unit/ber/ber_spec.rb spec/unit/ber/core_ext/array_spec.rb diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 854d4c6e..92ebfb45 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -24,7 +24,7 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] + s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 49158b30b256cc3c8458ab50327a1bc3835acff3 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 9 Oct 2014 19:26:44 -0700 Subject: [PATCH 118/435] Disable Rubinius 2.x It works, but to be practical it's too slow to care about for now. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dcd29b95..4dd7b6dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ rvm: - 2.1.2 - jruby-19mode - rbx-19mode - - rbx-2 + # - rbx-2 matrix: allow_failures: - rvm: jruby-19mode From 028402ba46f403dd7ff9f75a46382f063f600c1e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:13:15 -0700 Subject: [PATCH 119/435] rename to test_ber.rb --- test/ber/{ber_spec.rb => test_ber.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/ber/{ber_spec.rb => test_ber.rb} (100%) diff --git a/test/ber/ber_spec.rb b/test/ber/test_ber.rb similarity index 100% rename from test/ber/ber_spec.rb rename to test/ber/test_ber.rb From 1538672cd6ba821df84726cc1e16fea4a2c26932 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:13:22 -0700 Subject: [PATCH 120/435] convert to test/unit --- test/ber/test_ber.rb | 205 ++++++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 110 deletions(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 45e134a4..7568addb 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,140 +1,125 @@ -require 'spec_helper' +require 'common' -require 'net/ber' -require 'net/ldap' +class TestBEREncoding < Test::Unit::TestCase + def test_empty_array + assert_equal [], [].to_ber.read_ber + end -describe "BER encoding of" do + def test_array + ary = [1,2,3] + encoded_ary = ary.map { |el| el.to_ber }.to_ber - RSpec::Matchers.define :properly_encode_and_decode do - match do |given| - given.to_ber.read_ber.should == given - end + assert_equal ary, encoded_ary.read_ber end - context "arrays" do - it "should properly encode/decode []" do - [].should properly_encode_and_decode - end - it "should properly encode/decode [1,2,3]" do - ary = [1,2,3] - encoded_ary = ary.map { |el| el.to_ber }.to_ber + def test_true + assert_equal "\x01\x01\x01", true.to_ber + end - encoded_ary.read_ber.should == ary - end + def test_false + assert_equal "\x01\x01\x00", false.to_ber end - context "booleans" do - it "should encode true" do - true.to_ber.should == "\x01\x01\x01" - end - it "should encode false" do - false.to_ber.should == "\x01\x01\x00" + + # Sample based + { + 0 => "\x02\x01\x00", + 1 => "\x02\x01\x01", + 127 => "\x02\x01\x7F", + 128 => "\x02\x01\x80", + 255 => "\x02\x01\xFF", + 256 => "\x02\x02\x01\x00", + 65535 => "\x02\x02\xFF\xFF", + 65536 => "\x02\x03\x01\x00\x00", + 16_777_215 => "\x02\x03\xFF\xFF\xFF", + 0x01000000 => "\x02\x04\x01\x00\x00\x00", + 0x3FFFFFFF => "\x02\x04\x3F\xFF\xFF\xFF", + 0x4FFFFFFF => "\x02\x04\x4F\xFF\xFF\xFF", + + # Some odd samples... + 5 => "\002\001\005", + 500 => "\002\002\001\364", + 50_000 => "\x02\x02\xC3P", + 5_000_000_000 => "\002\005\001*\005\362\000" + }.each do |number, expected_encoding| + define_method "test_encode_#{number}" do + assert_equal expected_encoding.b, number.to_ber end end - context "numbers" do - # Sample based - { - 0 => raw_string("\x02\x01\x00"), - 1 => raw_string("\x02\x01\x01"), - 127 => raw_string("\x02\x01\x7F"), - 128 => raw_string("\x02\x01\x80"), - 255 => raw_string("\x02\x01\xFF"), - 256 => raw_string("\x02\x02\x01\x00"), - 65535 => raw_string("\x02\x02\xFF\xFF"), - 65536 => raw_string("\x02\x03\x01\x00\x00"), - 16_777_215 => raw_string("\x02\x03\xFF\xFF\xFF"), - 0x01000000 => raw_string("\x02\x04\x01\x00\x00\x00"), - 0x3FFFFFFF => raw_string("\x02\x04\x3F\xFF\xFF\xFF"), - 0x4FFFFFFF => raw_string("\x02\x04\x4F\xFF\xFF\xFF"), - - # Some odd samples... - 5 => raw_string("\002\001\005"), - 500 => raw_string("\002\002\001\364"), - 50_000 => raw_string("\x02\x02\xC3P"), - 5_000_000_000 => raw_string("\002\005\001*\005\362\000") - }.each do |number, expected_encoding| - it "should encode #{number} as #{expected_encoding.inspect}" do - number.to_ber.should == expected_encoding - end + + # Round-trip encoding: This is mostly to be sure to cover Bignums well. + def test_powers_of_two + 100.times do |p| + n = 2 << p + + assert_equal n, n.to_ber.read_ber end + end + + def test_powers_of_ten + 100.times do |p| + n = 5 * 10**p - # Round-trip encoding: This is mostly to be sure to cover Bignums well. - context "when decoding with #read_ber" do - it "should correctly handle powers of two" do - 100.times do |p| - n = 2 << p - - n.should properly_encode_and_decode - end - end - it "should correctly handle powers of ten" do - 100.times do |p| - n = 5 * 10**p - - n.should properly_encode_and_decode - end - end + assert_equal n, n.to_ber.read_ber end end + if "Ruby 1.9".respond_to?(:encoding) - context "strings" do - it "should properly encode UTF-8 strings" do - "\u00e5".force_encoding("UTF-8").to_ber.should == - raw_string("\x04\x02\xC3\xA5") - end - it "should properly encode strings encodable as UTF-8" do - "teststring".encode("US-ASCII").to_ber.should == "\x04\nteststring" - end - it "should properly encode binary data strings using to_ber_bin" do - # This is used for searching for GUIDs in Active Directory - ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == - raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") - end - it "should not fail on strings that can not be converted to UTF-8" do - expect { "\x81".to_ber }.not_to raise_error - end + def test_encode_utf8_strings + assert_equal "\x04\x02\xC3\xA5".b, "\u00e5".force_encoding("UTF-8").to_ber end - end -end -describe "BER decoding of" do - context "numbers" do - it "should decode #{"\002\001\006".inspect} (6)" do - "\002\001\006".read_ber(Net::LDAP::AsnSyntax).should == 6 + def test_utf8_encodable_strings + assert_equal "\x04\nteststring", "teststring".encode("US-ASCII").to_ber end - it "should decode #{"\004\007testing".inspect} ('testing')" do - "\004\007testing".read_ber(Net::LDAP::AsnSyntax).should == 'testing' + + def test_encode_binary_data + # This is used for searching for GUIDs in Active Directory + assert_equal "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16".b, + ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin end - it "should decode an ldap bind request" do - "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus". - read_ber(Net::LDAP::AsnSyntax).should == - [1, [3, "Administrator", "ad_is_bogus"]] + + def test_non_utf8_encodable_strings + assert_equal "\x04\x01\x81".b, "\x81".to_ber end end end -describe Net::BER::BerIdentifiedString do - describe "initialize" do - subject { Net::BER::BerIdentifiedString.new(data) } +class TestBERDecoding < Test::Unit::TestCase + def test_decode_number + assert_equal 6, "\002\001\006".read_ber(Net::LDAP::AsnSyntax) + end - context "binary data" do - let(:data) { ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") } + def test_decode_string + assert_equal "testing", "\004\007testing".read_ber(Net::LDAP::AsnSyntax) + end - specify { subject.valid_encoding?.should == true } - specify { subject.encoding.name.should == "ASCII-8BIT" } - end + def test_decode_ldap_bind_request + assert_equal [1, [3, "Administrator", "ad_is_bogus"]], "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus".read_ber(Net::LDAP::AsnSyntax) + end +end - context "ascii data in UTF-8" do - let(:data) { "some text".force_encoding("UTF-8") } +class TestBERIdentifiedString < Test::Unit::TestCase + def test_binary_data + data = ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") + bis = Net::BER::BerIdentifiedString.new(data) - specify { subject.valid_encoding?.should == true } - specify { subject.encoding.name.should == "UTF-8" } - end + assert_predicate bis, :valid_encoding? + assert_equal "ASCII-8BIT", bis.encoding.name + end - context "UTF-8 data in UTF-8" do - let(:data) { ["e4b8ad"].pack("H*").force_encoding("UTF-8") } + def test_ascii_data_in_utf8 + data = "some text".force_encoding("UTF-8") + bis = Net::BER::BerIdentifiedString.new(data) - specify { subject.valid_encoding?.should == true } - specify { subject.encoding.name.should == "UTF-8" } - end + assert_predicate bis, :valid_encoding? + assert_equal "UTF-8", bis.encoding.name + end + + def test_ut8_data_in_utf8 + data = ["e4b8ad"].pack("H*").force_encoding("UTF-8") + bis = Net::BER::BerIdentifiedString.new(data) + + assert_predicate bis, :valid_encoding? + assert_equal "UTF-8", bis.encoding.name end end From a2ff68f684f8e5dc25d85c7a54ca434ba56e6ac8 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:18:05 -0700 Subject: [PATCH 121/435] rename to test_array --- test/ber/core_ext/{array_spec.rb => test_array.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/ber/core_ext/{array_spec.rb => test_array.rb} (100%) diff --git a/test/ber/core_ext/array_spec.rb b/test/ber/core_ext/test_array.rb similarity index 100% rename from test/ber/core_ext/array_spec.rb rename to test/ber/core_ext/test_array.rb From f23838fee74aef862b73ea3aad861094bdd1f456 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:18:13 -0700 Subject: [PATCH 122/435] convert to test/unit --- test/ber/core_ext/test_array.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index c8a6b4eb..e8df3ffb 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -1,24 +1,22 @@ -require 'spec_helper' -require 'metaid' +require 'common' -describe Array, "when extended with BER core extensions" do - - it "should correctly convert a control code array" do +class TestBERArrayExtension < Test::Unit::TestCase + def test_control_code_array control_codes = [] control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence control_codes << ['1.7.9'.to_ber, false.to_ber].to_ber_sequence control_codes = control_codes.to_ber_sequence res = [['1.2.3', true],['1.7.9',false]].to_ber_control - res.should eq(control_codes) + assert_equal control_codes, res end - it "should wrap the array in another array if a nested array is not passed" do + def test_wrap_array_if_not_nested result1 = ['1.2.3', true].to_ber_control result2 = [['1.2.3', true]].to_ber_control - result1.should eq(result2) + assert_equal result2, result1 end - it "should return an empty string if an empty array is passed" do - [].to_ber_control.should be_empty + def test_empty_string_if_empty_array + assert_equal "", [].to_ber_control end end From edb924180277fd51fe4ac19ac1859b68880e9c65 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:40:24 -0700 Subject: [PATCH 123/435] rename to test_string --- test/ber/core_ext/{string_spec.rb => test_string.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/ber/core_ext/{string_spec.rb => test_string.rb} (100%) diff --git a/test/ber/core_ext/string_spec.rb b/test/ber/core_ext/test_string.rb similarity index 100% rename from test/ber/core_ext/string_spec.rb rename to test/ber/core_ext/test_string.rb From fa89e22cadfe6fdb640b1bdc7e09c8b331a0293e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 10:40:35 -0700 Subject: [PATCH 124/435] convert to test/unit --- test/ber/core_ext/test_string.rb | 62 ++++++++++---------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index edcd4403..3d262ba1 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -1,51 +1,25 @@ -require 'spec_helper' -require 'metaid' +require 'common' -describe String, "when extended with BER core extensions" do - describe "<- #read_ber! (consuming read_ber method)" do - context "when passed an ldap bind request and some extra data" do - attr_reader :str, :result - before(:each) do - @str = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED") - @result = str.read_ber!(Net::LDAP::AsnSyntax) - end - - it "should correctly parse the ber message" do - result.should == [1, [3, "Administrator", "ad_is_bogus"]] - end - it "should leave unconsumed part of message in place" do - str.should == " UNCONSUMED" - end - - context "if an exception occurs during #read_ber" do - attr_reader :initial_value - before(:each) do - stub_exception_class = Class.new(StandardError) +class TestBERStringExtension < Test::Unit::TestCase + def setup + @bind_request = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED".b + @result = @bind_request.read_ber!(Net::LDAP::AsnSyntax) + end - @initial_value = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus") - @str = initial_value.dup + def test_parse_ber + assert_equal [1, [3, "Administrator", "ad_is_bogus"]], @result + end - # Defines a string - io = StringIO.new(initial_value) - io.meta_def :read_ber do |syntax| - read - raise stub_exception_class - end - flexmock(StringIO).should_receive(:new).and_return(io) + def test_unconsumed_message + assert_equal " UNCONSUMED", @bind_request + end - begin - str.read_ber!(Net::LDAP::AsnSyntax) - rescue stub_exception_class - # EMPTY ON PURPOSE - else - raise "The stub code should raise an exception!" - end - end + def test_exception_does_not_modify_string + original = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus".b + duplicate = original.dup + flexmock(StringIO).any_instance.should_receive(:read_ber).and_raise(Net::BER::BerError) + duplicate.read_ber!(Net::LDAP::AsnSyntax) rescue Net::BER::BerError - it "should not modify string" do - str.should == initial_value - end - end - end + assert_equal original, duplicate end end From d30ce56e1a59ed2df9f893476ab127a2a547f7a7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 11:02:09 -0700 Subject: [PATCH 125/435] convert to test/unit --- spec/unit/ldap/dn_spec.rb | 80 --------------------------------------- test/test_dn.rb | 44 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 80 deletions(-) delete mode 100644 spec/unit/ldap/dn_spec.rb create mode 100644 test/test_dn.rb diff --git a/spec/unit/ldap/dn_spec.rb b/spec/unit/ldap/dn_spec.rb deleted file mode 100644 index 8d1b5852..00000000 --- a/spec/unit/ldap/dn_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -require 'spec_helper' -require 'net/ldap/dn' - -describe Net::LDAP::DN do - describe "<- .construct" do - attr_reader :dn - - before(:each) do - @dn = Net::LDAP::DN.new('cn', ',+"\\<>;', 'ou=company') - end - - it "should construct a Net::LDAP::DN" do - dn.should be_an_instance_of(Net::LDAP::DN) - end - - it "should escape all the required characters" do - dn.to_s.should == 'cn=\\,\\+\\"\\\\\\<\\>\\;,ou=company' - end - end - - describe "<- .to_a" do - context "parsing" do - { - 'cn=James, ou=Company\\,\\20LLC' => ['cn','James','ou','Company, LLC'], - 'cn = \ James , ou = "Comp\28ny" ' => ['cn',' James','ou','Comp(ny'], - '1.23.4= #A3B4D5 ,ou=Company' => ['1.23.4','#A3B4D5','ou','Company'], - }.each do |key, value| - context "(#{key})" do - attr_reader :dn - - before(:each) do - @dn = Net::LDAP::DN.new(key) - end - - it "should decode into a Net::LDAP::DN" do - dn.should be_an_instance_of(Net::LDAP::DN) - end - - it "should return the correct array" do - dn.to_a.should == value - end - end - end - end - - context "parsing bad input" do - [ - 'cn=James,', - 'cn=#aa aa', - 'cn="James', - 'cn=J\ames', - 'cn=\\', - '1.2.d=Value', - 'd1.2=Value', - ].each do |value| - context "(#{value})" do - attr_reader :dn - - before(:each) do - @dn = Net::LDAP::DN.new(value) - end - - it "should decode into a Net::LDAP::DN" do - dn.should be_an_instance_of(Net::LDAP::DN) - end - - it "should raise an error on parsing" do - lambda { dn.to_a }.should raise_error - end - end - end - end - end - - describe "<- .escape(str)" do - it "should escape ,, +, \", \\, <, >, and ;" do - Net::LDAP::DN.escape(',+"\\<>;').should == '\\,\\+\\"\\\\\\<\\>\\;' - end - end -end diff --git a/test/test_dn.rb b/test/test_dn.rb new file mode 100644 index 00000000..0bb47760 --- /dev/null +++ b/test/test_dn.rb @@ -0,0 +1,44 @@ +require 'common' +require 'net/ldap/dn' + +class TestDN < Test::Unit::TestCase + def test_escape + assert_equal '\\,\\+\\"\\\\\\<\\>\\;', Net::LDAP::DN.escape(',+"\\<>;') + end + + def test_escape_on_initialize + dn = Net::LDAP::DN.new('cn', ',+"\\<>;', 'ou=company') + assert_equal 'cn=\\,\\+\\"\\\\\\<\\>\\;,ou=company', dn.to_s + end + + def test_to_a + dn = Net::LDAP::DN.new('cn=James, ou=Company\\,\\20LLC') + assert_equal ['cn','James','ou','Company, LLC'], dn.to_a + end + + def test_to_a_parenthesis + dn = Net::LDAP::DN.new('cn = \ James , ou = "Comp\28ny" ') + assert_equal ['cn',' James','ou','Comp(ny'], dn.to_a + end + + def test_to_a_hash_symbol + dn = Net::LDAP::DN.new('1.23.4= #A3B4D5 ,ou=Company') + assert_equal ['1.23.4','#A3B4D5','ou','Company'], dn.to_a + end + + # TODO: raise a more specific exception than RuntimeError + def test_bad_input_raises_error + [ + 'cn=James,', + 'cn=#aa aa', + 'cn="James', + 'cn=J\ames', + 'cn=\\', + '1.2.d=Value', + 'd1.2=Value', + ].each do |input| + dn = Net::LDAP::DN.new(input) + assert_raises(RuntimeError) { dn.to_a } + end + end +end From 241527626444c21fbac05bcab9bb59f0021cfcd9 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 11:09:34 -0700 Subject: [PATCH 126/435] add additional ldif parsing entry tests --- test/test_entry.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test_entry.rb b/test/test_entry.rb index b270069f..c3ed6ff6 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -40,3 +40,26 @@ def test_case_insensitive_attribute_names assert_equal ['Jensen'], @entry['SN'] end end + +class TestEntryLDIF < Test::Unit::TestCase + def setup + @entry = Net::LDAP::Entry.from_single_ldif_string( + %Q{dn: something +foo: foo +barAttribute: bar + }) + end + + def test_attribute + assert_equal ['foo'], @entry.foo + assert_equal ['foo'], @entry.Foo + end + + def test_modify_attribute + @entry.foo = 'bar' + assert_equal ['bar'], @entry.foo + + @entry.fOo= 'baz' + assert_equal ['baz'], @entry.foo + end +end From 006d45484966509d8644c8c78c2604d47d447336 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 11:19:10 -0700 Subject: [PATCH 127/435] moved tests over to test/test_entry --- spec/unit/ldap/entry_spec.rb | 51 ------------------------------------ 1 file changed, 51 deletions(-) delete mode 100644 spec/unit/ldap/entry_spec.rb diff --git a/spec/unit/ldap/entry_spec.rb b/spec/unit/ldap/entry_spec.rb deleted file mode 100644 index e0270cbd..00000000 --- a/spec/unit/ldap/entry_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'spec_helper' - -describe Net::LDAP::Entry do - attr_reader :entry - before(:each) do - @entry = Net::LDAP::Entry.from_single_ldif_string( - %Q{dn: something -foo: foo -barAttribute: bar - } - ) - end - - describe "entry access" do - it "should always respond to #dn" do - entry.should respond_to(:dn) - end - - context "<- #foo" do - it "should respond_to?" do - entry.should respond_to(:foo) - end - it "should return 'foo'" do - entry.foo.should == ['foo'] - end - end - context "<- #Foo" do - it "should respond_to?" do - entry.should respond_to(:Foo) - end - it "should return 'foo'" do - entry.foo.should == ['foo'] - end - end - context "<- #foo=" do - it "should respond_to?" do - entry.should respond_to(:foo=) - end - it "should set 'foo'" do - entry.foo= 'bar' - entry.foo.should == ['bar'] - end - end - context "<- #fOo=" do - it "should return 'foo'" do - entry.fOo= 'bar' - entry.fOo.should == ['bar'] - end - end - end -end \ No newline at end of file From 98eea8e12e5986d9a55965df6415ed58458531b5 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:09:53 -0700 Subject: [PATCH 128/435] rename test_filter_parser --- .../unit/ldap/filter_parser_spec.rb => test/test_filter_parser.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/unit/ldap/filter_parser_spec.rb => test/test_filter_parser.rb (100%) diff --git a/spec/unit/ldap/filter_parser_spec.rb b/test/test_filter_parser.rb similarity index 100% rename from spec/unit/ldap/filter_parser_spec.rb rename to test/test_filter_parser.rb From f73b9c1194cf51b743815254339a7e1a39788bed Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:10:02 -0700 Subject: [PATCH 129/435] convert to test/unit --- test/test_filter_parser.rb | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index c65c615a..06797542 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,26 +1,16 @@ # encoding: utf-8 -require 'spec_helper' +require 'common' -describe Net::LDAP::Filter::FilterParser do +class TestFilterParser < Test::Unit::TestCase + def test_ascii + assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=name)") + end + + def test_multibyte_characters + assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=名前)") + end - describe "#parse" do - context "Given ASCIIs as filter string" do - let(:filter_string) { "(cn=name)" } - specify "should generate filter object" do - expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter - end - end - context "Given string including multibyte chars as filter string" do - let(:filter_string) { "(cn=名前)" } - specify "should generate filter object" do - expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter - end - end - context "Given string including colons ':'" do - let(:filter_string) { "(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" } - specify "should generate filter object" do - expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter - end - end + def test_colons + 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)") end end From c6f7c1ff86953f66951e39392c3a0fa80b872d98 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:42:22 -0700 Subject: [PATCH 130/435] convert filter spec to test/unit --- spec/unit/ldap/filter_spec.rb | 115 ---------------------------------- test/test_filter.rb | 98 ++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 116 deletions(-) delete mode 100644 spec/unit/ldap/filter_spec.rb diff --git a/spec/unit/ldap/filter_spec.rb b/spec/unit/ldap/filter_spec.rb deleted file mode 100644 index 06fd3b80..00000000 --- a/spec/unit/ldap/filter_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -require 'spec_helper' - -describe Net::LDAP::Filter do - describe "<- .ex(attr, value)" do - context "('foo', 'bar')" do - attr_reader :filter - before(:each) do - @filter = Net::LDAP::Filter.ex('foo', 'bar') - end - it "should convert to 'foo:=bar'" do - filter.to_s.should == '(foo:=bar)' - end - it "should survive roundtrip via to_s/from_rfc2254" do - Net::LDAP::Filter.from_rfc2254(filter.to_s).should == filter - end - it "should survive roundtrip conversion to/from ber" do - ber = filter.to_ber - Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should == - filter - end - end - context "various legal inputs" do - [ - '(o:dn:=Ace Industry)', - '(:dn:2.4.8.10:=Dino)', - '(cn:dn:1.2.3.4.5:=John Smith)', - '(sn:dn:2.4.6.8.10:=Barbara Jones)', - '(&(sn:dn:2.4.6.8.10:=Barbara Jones))' - ].each do |filter_str| - context "from_rfc2254(#{filter_str.inspect})" do - attr_reader :filter - before(:each) do - @filter = Net::LDAP::Filter.from_rfc2254(filter_str) - end - - it "should decode into a Net::LDAP::Filter" do - filter.should be_an_instance_of(Net::LDAP::Filter) - end - it "should survive roundtrip conversion to/from ber" do - ber = filter.to_ber - Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should == - filter - end - end - end - end - end - describe "<- .construct" do - it "should accept apostrophes in filters (regression)" do - Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)" - end - end - - describe "convenience filter constructors" do - def eq(attribute, value) - described_class.eq(attribute, value) - end - describe "<- .equals(attr, val)" do - it "should delegate to .eq with escaping" do - described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo') - end - end - describe "<- .begins(attr, val)" do - it "should delegate to .eq with escaping" do - described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*') - end - end - describe "<- .ends(attr, val)" do - it "should delegate to .eq with escaping" do - described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo') - end - end - describe "<- .contains(attr, val)" do - it "should delegate to .eq with escaping" do - described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*') - end - end - end - describe "<- .escape(str)" do - it "should escape nul, *, (, ) and \\" do - Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C" - end - end - - context 'with a well-known BER string' do - ber = raw_string("\xa4\x2d" \ - "\x04\x0b" "objectclass" \ - "\x30\x1e" \ - "\x80\x08" "foo" "*\\" "bar" \ - "\x81\x08" "foo" "*\\" "bar" \ - "\x82\x08" "foo" "*\\" "bar") - - describe "<- .to_ber" do - [ - "foo" "\\2A\\5C" "bar", - "foo" "\\2a\\5c" "bar", - "foo" "\\2A\\5c" "bar", - "foo" "\\2a\\5C" "bar" - ].each do |escaped| - it 'unescapes escaped characters' do - filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}") - filter.to_ber.should == ber - end - end - end - - describe '<- .parse_ber' do - it 'escapes characters' do - escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar") - filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) - filter.to_s.should == "(objectclass=#{escaped}*#{escaped}*#{escaped})" - end - end - end -end diff --git a/test/test_filter.rb b/test/test_filter.rb index 03436e03..88ec98a9 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -28,7 +28,7 @@ def test_convenience_filters assert_equal("(uid=\\2A)", Filter.equals("uid", "*").to_s) assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s) assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s) - assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) + assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) end def test_c2 @@ -120,3 +120,99 @@ def test_ber_from_rfc2254_filter end end end + +# tests ported over from rspec. Not sure if these overlap with the above +# https://github.com/ruby-ldap/ruby-net-ldap/pull/121 +class TestFilterRSpec < Test::Unit::TestCase + def test_ex_convert + assert_equal '(foo:=bar)', Net::LDAP::Filter.ex('foo', 'bar').to_s + end + + def test_ex_rfc2254_roundtrip + filter = Net::LDAP::Filter.ex('foo', 'bar') + assert_equal filter, Net::LDAP::Filter.from_rfc2254(filter.to_s) + end + + def test_ber_conversion + filter = Net::LDAP::Filter.ex('foo', 'bar') + ber = filter.to_ber + assert_equal filter, Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) + end + + [ + '(o:dn:=Ace Industry)', + '(:dn:2.4.8.10:=Dino)', + '(cn:dn:1.2.3.4.5:=John Smith)', + '(sn:dn:2.4.6.8.10:=Barbara Jones)', + '(&(sn:dn:2.4.6.8.10:=Barbara Jones))' + ].each_with_index do |filter_str, index| + define_method "test_decode_filter_#{index}" do + filter = Net::LDAP::Filter.from_rfc2254(filter_str) + assert_kind_of Net::LDAP::Filter, filter + end + + define_method "test_ber_conversion_#{index}" do + filter = Net::LDAP::Filter.from_rfc2254(filter_str) + ber = Net::LDAP::Filter.from_rfc2254(filter_str).to_ber + assert_equal filter, Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) + end + end + + def test_apostrophes + assert_equal "(uid=O'Keefe)", Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254 + end + + def test_equals + assert_equal Net::LDAP::Filter.eq('dn', 'f\2Aoo'), Net::LDAP::Filter.equals('dn', 'f*oo') + end + + def test_begins + assert_equal Net::LDAP::Filter.eq('dn', 'f\2Aoo*'), Net::LDAP::Filter.begins('dn', 'f*oo') + end + + def test_ends + assert_equal Net::LDAP::Filter.eq('dn', '*f\2Aoo'), Net::LDAP::Filter.ends('dn', 'f*oo') + end + + def test_contains + assert_equal Net::LDAP::Filter.eq('dn', '*f\2Aoo*'), Net::LDAP::Filter.contains('dn', 'f*oo') + end + + def test_escape + # escapes nul, *, (, ) and \\ + assert_equal "\\00\\2A\\28\\29\\5C", Net::LDAP::Filter.escape("\0*()\\") + end + + def test_well_known_ber_string + ber = "\xa4\x2d" \ + "\x04\x0b" "objectclass" \ + "\x30\x1e" \ + "\x80\x08" "foo" "*\\" "bar" \ + "\x81\x08" "foo" "*\\" "bar" \ + "\x82\x08" "foo" "*\\" "bar".b + + [ + "foo" "\\2A\\5C" "bar", + "foo" "\\2a\\5c" "bar", + "foo" "\\2A\\5c" "bar", + "foo" "\\2a\\5C" "bar" + ].each do |escaped| + # unescapes escaped characters + filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}") + assert_equal ber, filter.to_ber + end + end + + def test_parse_ber_escapes_characters + ber = "\xa4\x2d" \ + "\x04\x0b" "objectclass" \ + "\x30\x1e" \ + "\x80\x08" "foo" "*\\" "bar" \ + "\x81\x08" "foo" "*\\" "bar" \ + "\x82\x08" "foo" "*\\" "bar".b + + escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar") + filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) + assert_equal "(objectclass=#{escaped}*#{escaped}*#{escaped})", filter.to_s + end +end From 7f60acec3b2bb54f916241d4d0f4ff520dacc70b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:58:19 -0700 Subject: [PATCH 131/435] rename test_search --- spec/unit/ldap/search_spec.rb => test/test_search.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/unit/ldap/search_spec.rb => test/test_search.rb (100%) diff --git a/spec/unit/ldap/search_spec.rb b/test/test_search.rb similarity index 100% rename from spec/unit/ldap/search_spec.rb rename to test/test_search.rb From b2d49b945b5fafcc83febbf6c27eb0f0c11b2d79 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:58:39 -0700 Subject: [PATCH 132/435] add MockInstrumentationService to common --- test/common.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/common.rb b/test/common.rb index 1ff8d12a..eea28c24 100644 --- a/test/common.rb +++ b/test/common.rb @@ -2,3 +2,21 @@ require 'test/unit' require 'net/ldap' require 'flexmock/test_unit' + +class MockInstrumentationService + def initialize + @events = {} + end + + def instrument(event, payload) + result = yield(payload) + @events[event] ||= [] + @events[event] << [payload, result] + result + end + + def subscribe(event) + @events[event] ||= [] + @events[event] + end +end From 231bd873506c50a68e1b14fb714dbf15c387d4c6 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 12:58:47 -0700 Subject: [PATCH 133/435] convert to test/unit --- test/test_search.rb | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/test/test_search.rb b/test/test_search.rb index 55aa94db..23f1f7ff 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,49 +1,39 @@ # -*- ruby encoding: utf-8 -*- +require 'common' -describe Net::LDAP, "search method" do +class TestSearch < Test::Unit::TestCase class FakeConnection def search(args) OpenStruct.new(:result_code => 1, :message => "error", :success? => false) end end - before(:each) do + def setup @service = MockInstrumentationService.new @connection = Net::LDAP.new :instrumentation_service => @service @connection.instance_variable_set(:@open_connection, FakeConnection.new) end - context "when :return_result => true" do - it "should return nil upon error" do - result_set = @connection.search(:return_result => true) - result_set.should be_nil - end + def test_true_result + assert_nil @connection.search(:return_result => true) end - context "when :return_result => false" do - it "should return false upon error" do - result = @connection.search(:return_result => false) - result.should == false - end + def test_false_result + refute @connection.search(:return_result => false) end - context "When :return_result is not given" do - it "should return nil upon error" do - result_set = @connection.search - result_set.should be_nil - end + def test_no_result + assert_nil @connection.search end - context "when instrumentation_service is configured" do - it "should publish a search.net_ldap event" do - events = @service.subscribe "search.net_ldap" + def test_instrumentation_publishes_event + events = @service.subscribe "search.net_ldap" - @connection.search :filter => "test" + @connection.search(:filter => "test") - payload, result = events.pop - payload.should have_key(:result) - payload.should have_key(:filter) - payload[:filter].should == "test" - end + payload, result = events.pop + assert payload.has_key?(:result) + assert payload.has_key?(:filter) + assert_equal "test", payload[:filter] end end From ca1c0830ff9834fb562d8f750ad3c7f279a075ea Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 13:00:02 -0700 Subject: [PATCH 134/435] rename test_ldap --- spec/unit/ldap_spec.rb => test/test_ldap.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/unit/ldap_spec.rb => test/test_ldap.rb (100%) diff --git a/spec/unit/ldap_spec.rb b/test/test_ldap.rb similarity index 100% rename from spec/unit/ldap_spec.rb rename to test/test_ldap.rb From 9471294865c0032ea8f970d72e655aeda9f3e9f3 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 13:00:12 -0700 Subject: [PATCH 135/435] make class name unique --- test/test_ldap_connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index a3643016..f74d989a 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,6 +1,6 @@ require 'common' -class TestLDAP < Test::Unit::TestCase +class TestLDAPConnection < Test::Unit::TestCase def test_modify_ops_delete args = { :operations => [ [ :delete, "mail" ] ] } result = Net::LDAP::Connection.modify_ops(args[:operations]) From d40e19b8dffb43bf78b4214b55205f6cb392d93d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 14:40:48 -0700 Subject: [PATCH 136/435] convert tests to test/unit --- test/test_ldap.rb | 242 +++++------------------------------ test/test_ldap_connection.rb | 144 +++++++++++++++++++++ 2 files changed, 175 insertions(+), 211 deletions(-) diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 8f756b68..096dfac5 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -1,223 +1,43 @@ -require 'spec_helper' - -describe Net::LDAP do - describe "initialize" do - context "when instrumentation is configured" do - before do - @connection = flexmock(:connection, :close => true) - flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection) - - @service = MockInstrumentationService.new - end - - subject do - Net::LDAP.new \ - :server => "test.mocked.com", :port => 636, - :force_no_page => true, # so server capabilities are not queried - :instrumentation_service => @service - end - - it "should instrument bind" do - events = @service.subscribe "bind.net_ldap" - - bind_result = flexmock(:bind_result, :success? => true) - @connection.should_receive(:bind).with(Hash).and_return(bind_result) - - subject.bind.should == true - - payload, result = events.pop - result.should == true - payload[:bind].should == bind_result - end - - it "should instrument search" do - events = @service.subscribe "search.net_ldap" - - @connection.should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) - @connection.should_receive(:search).with(Hash, Proc). - yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). - and_return(flexmock(:search_result, :success? => true, :result_code => 0)) - - subject.search(:filter => "(uid=user1)").should_not be_nil - - payload, result = events.pop - result.should == [entry] - payload[:result].should == [entry] - payload[:filter].should == "(uid=user1)" - end - end - end -end - -describe Net::LDAP::Connection do - describe "initialize" do - context "when host is not responding" do - before(:each) do - flexmock(TCPSocket). - should_receive(:new).and_raise(Errno::ECONNREFUSED) - end - - it "should raise LdapError" do - lambda { - Net::LDAP::Connection.new( - :server => 'test.mocked.com', - :port => 636) - }.should raise_error(Net::LDAP::LdapError) - end - end - context "when host is blocking the port" do - before(:each) do - flexmock(TCPSocket). - should_receive(:new).and_raise(SocketError) - end - - it "should raise LdapError" do - lambda { - Net::LDAP::Connection.new( - :server => 'test.mocked.com', - :port => 636) - }.should raise_error(Net::LDAP::LdapError) - end - end - context "on other exceptions" do - before(:each) do - flexmock(TCPSocket). - should_receive(:new).and_raise(NameError) - end - - it "should rethrow the exception" do - lambda { - Net::LDAP::Connection.new( - :server => 'test.mocked.com', - :port => 636) - }.should raise_error(NameError) - end - end +require 'common' + +class TestLDAPInstrumentation < Test::Unit::TestCase + def setup + @connection = flexmock(:connection, :close => true) + flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection) + + @service = MockInstrumentationService.new + @ldap = Net::LDAP.new \ + :server => "test.mocked.com", :port => 636, + :force_no_page => true, # so server capabilities are not queried + :instrumentation_service => @service end - context "populate error messages" do - before do - @tcp_socket = flexmock(:connection) - @tcp_socket.should_receive(:write) - flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) - end + def test_instrument_bind + events = @service.subscribe "bind.net_ldap" - subject { Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) } + bind_result = flexmock(:bind_result, :success? => true) + @connection.should_receive(:bind).with(Hash).and_return(bind_result) - it "should get back error messages if operation fails" do - ber = Net::BER::BerIdentifiedArray.new([53, "", "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]) + assert @ldap.bind - result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) - result.should be_failure - result.error_message.should == "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" - end - - it "shouldn't get back error messages if operation succeeds" do - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = Net::LDAP::PDU::ModifyResponse - @tcp_socket.should_receive(:read_ber).and_return([2, ber]) - - result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) - result.should be_success - result.error_message.should == "" - end + payload, result = events.pop + assert result + assert_equal bind_result, payload[:bind] end - context "instrumentation" do - before do - @tcp_socket = flexmock(:connection) - # handle write - @tcp_socket.should_receive(:write) - # return this mock - flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) - - @service = MockInstrumentationService.new - end - - subject do - Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636, - :instrumentation_service => @service) - end - - it "should publish a write.net_ldap_connection event" do - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(read_result) - - events = @service.subscribe "write.net_ldap_connection" - - result = subject.bind(method: :anon) - result.should be_success - - # a write event - payload, result = events.pop - payload.should have_key(:result) - payload.should have_key(:content_length) - end - - it "should publish a read.net_ldap_connection event" do - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(read_result) - - events = @service.subscribe "read.net_ldap_connection" - - result = subject.bind(method: :anon) - result.should be_success - - # a read event - payload, result = events.pop - payload.should have_key(:result) - result.should == read_result - end - - it "should publish a bind.net_ldap_connection event" do - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - ber.ber_identifier = Net::LDAP::PDU::BindResult - bind_result = [2, ber] - @tcp_socket.should_receive(:read_ber).and_return(bind_result) - - events = @service.subscribe "bind.net_ldap_connection" - - result = subject.bind(method: :anon) - result.should be_success - - # a read event - payload, result = events.pop - payload.should have_key(:result) - result.should be_success - end - - it "should publish a search.net_ldap_connection event" do - # search data - search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ - "uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local", - [ ["uid", ["user1"]] ] - ]]) - search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData - search_data = [2, search_data_ber] - # search result (end of results) - search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) - search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult - search_result = [2, search_result_ber] - @tcp_socket.should_receive(:read_ber).and_return(search_data). - and_return(search_result) + def test_instrument_search + events = @service.subscribe "search.net_ldap" - events = @service.subscribe "search.net_ldap_connection" + @connection.should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + @connection.should_receive(:search).with(Hash, Proc). + yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). + and_return(flexmock(:search_result, :success? => true, :result_code => 0)) - result = subject.search(filter: "(uid=user1)") - result.should be_success + refute_nil @ldap.search(:filter => "(uid=user1)") - # a search event - payload, result = events.pop - payload.should have_key(:result) - payload.should have_key(:filter) - payload[:filter].to_s.should == "(uid=user1)" - result.should be_truthy - end + payload, result = events.pop + assert_equal [entry], result + assert_equal [entry], payload[:result] + assert_equal "(uid=user1)", payload[:filter] end end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index f74d989a..37b52b3f 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,6 +1,27 @@ require 'common' class TestLDAPConnection < Test::Unit::TestCase + def test_unresponsive_host + assert_raise Net::LDAP::LdapError do + Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + end + end + + def test_blocked_port + flexmock(TCPSocket).should_receive(:new).and_raise(SocketError) + assert_raise Net::LDAP::LdapError do + Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + end + end + + def test_raises_unknown_exceptions + error = Class.new(StandardError) + flexmock(TCPSocket).should_receive(:new).and_raise(error) + assert_raise error do + Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + end + end + def test_modify_ops_delete args = { :operations => [ [ :delete, "mail" ] ] } result = Net::LDAP::Connection.modify_ops(args[:operations]) @@ -22,3 +43,126 @@ def test_modify_ops_replace assert_equal(expected, result) end end + + +class TestLDAPConnectionErrors < Test::Unit::TestCase + def setup + @tcp_socket = flexmock(:connection) + @tcp_socket.should_receive(:write) + flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + @connection = Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + end + + def test_error_failed_operation + ber = Net::BER::BerIdentifiedArray.new([53, "", "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]) + + result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) + assert_predicate result, :failure? + 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 + end + + def test_no_error_on_success + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::ModifyResponse + @tcp_socket.should_receive(:read_ber).and_return([2, ber]) + + result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) + assert_predicate result, :success? + assert_equal "", result.error_message + end +end + +class TestLDAPInstrumentation < Test::Unit::TestCase + def setup + @tcp_socket = flexmock(:connection) + @tcp_socket.should_receive(:write) + flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + + @service = MockInstrumentationService.new + @connection = Net::LDAP::Connection.new \ + :server => 'test.mocked.com', + :port => 636, + :instrumentation_service => @service + end + + def test_write_net_ldap_connection_event + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::BindResult + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) + + events = @service.subscribe "write.net_ldap_connection" + + result = @connection.bind(method: :anon) + assert_predicate result, :success? + + # a write event + payload, result = events.pop + assert payload.has_key?(:result) + assert payload.has_key?(:content_length) + end + + def test_read_net_ldap_connection_event + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::BindResult + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) + + events = @service.subscribe "read.net_ldap_connection" + + result = @connection.bind(method: :anon) + assert_predicate result, :success? + + # a read event + payload, result = events.pop + assert payload.has_key?(:result) + assert_equal read_result, result + end + + def test_bind_net_ldap_connection_event + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::BindResult + bind_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(bind_result) + + events = @service.subscribe "bind.net_ldap_connection" + + result = @connection.bind(method: :anon) + assert_predicate result, :success? + + # a read event + payload, result = events.pop + assert payload.has_key?(:result) + assert_predicate result, :success? + end + + def test_search_net_ldap_connection_event + # search data + search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ + "uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local", + [ ["uid", ["user1"]] ] + ]]) + search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData + search_data = [2, search_data_ber] + # search result (end of results) + search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult + search_result = [2, search_result_ber] + @tcp_socket.should_receive(:read_ber).and_return(search_data). + and_return(search_result) + + events = @service.subscribe "search.net_ldap_connection" + + result = @connection.search(filter: "(uid=user1)") + assert_predicate result, :success? + + # a search event + payload, result = events.pop + assert payload.has_key?(:result) + assert payload.has_key?(:filter) + assert_equal "(uid=user1)", payload[:filter].to_s + assert result + end +end From 903e459e7bde5b0ce03c839a8fcbf7a570a9eaf7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 14:50:42 -0700 Subject: [PATCH 137/435] fix deprecation any_instances --- test/ber/core_ext/test_string.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index 3d262ba1..8e185a67 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -17,7 +17,7 @@ def test_unconsumed_message def test_exception_does_not_modify_string original = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus".b duplicate = original.dup - flexmock(StringIO).any_instance.should_receive(:read_ber).and_raise(Net::BER::BerError) + flexmock(StringIO).new_instances.should_receive(:read_ber).and_raise(Net::BER::BerError) duplicate.read_ber!(Net::LDAP::AsnSyntax) rescue Net::BER::BerError assert_equal original, duplicate From dcfe8ae334889f634b6ba02e036b6e3043659be0 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 14:50:56 -0700 Subject: [PATCH 138/435] test doesn't like @ldap ivar --- test/test_ldap.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 096dfac5..ac0c28d5 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -6,7 +6,7 @@ def setup flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection) @service = MockInstrumentationService.new - @ldap = Net::LDAP.new \ + @subject = Net::LDAP.new \ :server => "test.mocked.com", :port => 636, :force_no_page => true, # so server capabilities are not queried :instrumentation_service => @service @@ -16,9 +16,9 @@ def test_instrument_bind events = @service.subscribe "bind.net_ldap" bind_result = flexmock(:bind_result, :success? => true) - @connection.should_receive(:bind).with(Hash).and_return(bind_result) + flexmock(@connection).should_receive(:bind).with(Hash).and_return(bind_result) - assert @ldap.bind + assert @subject.bind payload, result = events.pop assert result @@ -28,12 +28,12 @@ def test_instrument_bind def test_instrument_search events = @service.subscribe "search.net_ldap" - @connection.should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) - @connection.should_receive(:search).with(Hash, Proc). + flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + flexmock(@connection).should_receive(:search).with(Hash, Proc). yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). and_return(flexmock(:search_result, :success? => true, :result_code => 0)) - refute_nil @ldap.search(:filter => "(uid=user1)") + refute_nil @subject.search(:filter => "(uid=user1)") payload, result = events.pop assert_equal [entry], result From 89bb2ed6b77cb4f0efbe23d8cabb3d2dcb9025ca Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:04:00 -0700 Subject: [PATCH 139/435] remove spec_helper --- spec/spec_helper.rb | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 spec/spec_helper.rb diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 820dac30..00000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'net/ldap' - -RSpec.configure do |config| - config.mock_with :flexmock - - def raw_string(s) - # Conveniently, String#b only needs to be called when it exists - s.respond_to?(:b) ? s.b : s - end -end - -class MockInstrumentationService - def initialize - @events = {} - end - - def instrument(event, payload) - result = yield(payload) - @events[event] ||= [] - @events[event] << [payload, result] - result - end - - def subscribe(event) - @events[event] ||= [] - @events[event] - end -end From 197c3e92610a3d406baca4d75d679f906e61a5ae Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:05:33 -0700 Subject: [PATCH 140/435] remove unused metaid gem --- Hacking.rdoc | 1 - Rakefile | 3 +-- net-ldap.gemspec | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Hacking.rdoc b/Hacking.rdoc index 1db37cb2..56b96f83 100644 --- a/Hacking.rdoc +++ b/Hacking.rdoc @@ -57,7 +57,6 @@ installed using RubyGems. * *hoe* * *hoe-git* -* *metaid* * *rspec* * *flexmock* diff --git a/Rakefile b/Rakefile index 159a8a09..9ae108cb 100644 --- a/Rakefile +++ b/Rakefile @@ -30,7 +30,6 @@ Hoe.spec 'net-ldap' do |spec| spec.extra_dev_deps << [ "hoe-git", "~> 1" ] spec.extra_dev_deps << [ "hoe-gemspec", "~> 1" ] - spec.extra_dev_deps << [ "metaid", "~> 1" ] spec.extra_dev_deps << [ "flexmock", ">= 1.3.0" ] spec.extra_dev_deps << [ "rspec", "~> 2.0" ] @@ -70,7 +69,7 @@ namespace :old do end end -desc "Run a full set of integration and unit tests" +desc "Run a full set of integration and unit tests" task :cruise => [:test, :spec] # vim: syntax=ruby diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 854d4c6e..5eac193e 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -40,14 +40,12 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, ["~> 1"]) - s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, [">= 1.3.0"]) s.add_development_dependency(%q, ["~> 2.0"]) s.add_development_dependency(%q, [">= 2.9.1"]) else s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, [">= 1.3.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) @@ -55,7 +53,6 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} else s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, [">= 1.3.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) From a7377fb53d8c274922b95e330fef7c24e84be847 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:07:20 -0700 Subject: [PATCH 141/435] remove .autotest and .rspec --- .autotest | 11 ----------- .rspec | 2 -- Manifest.txt | 3 --- autotest/discover.rb | 1 - net-ldap.gemspec | 2 +- 5 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 .autotest delete mode 100644 .rspec delete mode 100644 autotest/discover.rb diff --git a/.autotest b/.autotest deleted file mode 100644 index f5f85be9..00000000 --- a/.autotest +++ /dev/null @@ -1,11 +0,0 @@ -require 'rubygems' -#require 'redgreen/autotest' -require 'autotest/timestamp' - -Autotest.add_hook :initialize do |autotest| - %w{.git .hg .DS_Store ._* tmp log doc}.each do |exception| - autotest.add_exception(exception) - end -end - -# vim: syntax=ruby diff --git a/.rspec b/.rspec deleted file mode 100644 index 7438fbe5..00000000 --- a/.rspec +++ /dev/null @@ -1,2 +0,0 @@ ---colour ---format documentation diff --git a/Manifest.txt b/Manifest.txt index bea51c0c..01181bc0 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,5 +1,3 @@ -.autotest -.rspec .travis.yml Contributors.rdoc Gemfile @@ -9,7 +7,6 @@ License.rdoc Manifest.txt README.rdoc Rakefile -autotest/discover.rb lib/net-ldap.rb lib/net/ber.rb lib/net/ber/ber_parser.rb diff --git a/autotest/discover.rb b/autotest/discover.rb deleted file mode 100644 index cd6892cc..00000000 --- a/autotest/discover.rb +++ /dev/null @@ -1 +0,0 @@ -Autotest.add_discovery { "rspec2" } diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 5eac193e..c37891e1 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -24,7 +24,7 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] + s.files = ["Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 1018963e80d118f628fda1b35aae1eebd1f963f7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:11:33 -0700 Subject: [PATCH 142/435] generate gemspec file list --- net-ldap.gemspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index c37891e1..12491f1f 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -24,7 +24,8 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = ["Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] + s.files = `git ls-files`.split $/ + s.test_files = s.files.grep(%r{^test}) s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 619c622fc7e853c92b9290e92747491633f3596b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:11:44 -0700 Subject: [PATCH 143/435] remove rspec --- Hacking.rdoc | 5 ++--- Rakefile | 1 - net-ldap.gemspec | 3 --- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Hacking.rdoc b/Hacking.rdoc index 56b96f83..56bf73f7 100644 --- a/Hacking.rdoc +++ b/Hacking.rdoc @@ -40,8 +40,8 @@ modification to +Contributors.rdoc+ to add yourself. == Tests -The Net::LDAP team uses RSpec for unit testing; all changes must have rspec -tests for any new or changed features. +The Net::LDAP team uses [Minitest](http://docs.seattlerb.org/minitest/) for unit +testing; all changes must have tests for any new or changed features. Your changes should have been tested against at least one real LDAP server; the current tests are not sufficient to find all possible bugs. It's unlikely that @@ -57,7 +57,6 @@ installed using RubyGems. * *hoe* * *hoe-git* -* *rspec* * *flexmock* == Participation diff --git a/Rakefile b/Rakefile index 9ae108cb..4db3f047 100644 --- a/Rakefile +++ b/Rakefile @@ -31,7 +31,6 @@ Hoe.spec 'net-ldap' do |spec| spec.extra_dev_deps << [ "hoe-git", "~> 1" ] spec.extra_dev_deps << [ "hoe-gemspec", "~> 1" ] spec.extra_dev_deps << [ "flexmock", ">= 1.3.0" ] - spec.extra_dev_deps << [ "rspec", "~> 2.0" ] spec.clean_globs << "coverage" diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 12491f1f..454ab446 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -42,20 +42,17 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, ["~> 1"]) s.add_development_dependency(%q, [">= 1.3.0"]) - s.add_development_dependency(%q, ["~> 2.0"]) s.add_development_dependency(%q, [">= 2.9.1"]) else s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, [">= 1.3.0"]) - s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) end else s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, ["~> 1"]) s.add_dependency(%q, [">= 1.3.0"]) - s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, [">= 2.9.1"]) end end From f2cec77a2dbea05813bb8a0e813f8fd125c1670e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 10 Oct 2014 15:13:52 -0700 Subject: [PATCH 144/435] rename common to test_helper --- test/ber/core_ext/test_array.rb | 2 +- test/ber/core_ext/test_string.rb | 2 +- test/ber/test_ber.rb | 2 +- test/test_dn.rb | 2 +- test/test_entry.rb | 2 +- test/test_filter.rb | 2 +- test/test_filter_parser.rb | 2 +- test/{common.rb => test_helper.rb} | 0 test/test_ldap_connection.rb | 2 +- test/test_ldif.rb | 2 +- test/test_password.rb | 2 +- test/test_rename.rb | 4 ++-- test/test_search.rb | 2 +- test/test_snmp.rb | 2 +- test/test_ssl_ber.rb | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) rename test/{common.rb => test_helper.rb} (100%) diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index e8df3ffb..cba9ea7a 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestBERArrayExtension < Test::Unit::TestCase def test_control_code_array diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index 8e185a67..95ece554 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestBERStringExtension < Test::Unit::TestCase def setup diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 7568addb..97bcf129 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestBEREncoding < Test::Unit::TestCase def test_empty_array diff --git a/test/test_dn.rb b/test/test_dn.rb index 0bb47760..b758b913 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' require 'net/ldap/dn' class TestDN < Test::Unit::TestCase diff --git a/test/test_entry.rb b/test/test_entry.rb index c3ed6ff6..90752c00 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestEntry < Test::Unit::TestCase def setup diff --git a/test/test_filter.rb b/test/test_filter.rb index 88ec98a9..62db542b 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestFilter < Test::Unit::TestCase Filter = Net::LDAP::Filter diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 06797542..ded4a026 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require 'common' +require 'test_helper' class TestFilterParser < Test::Unit::TestCase def test_ascii diff --git a/test/common.rb b/test/test_helper.rb similarity index 100% rename from test/common.rb rename to test/test_helper.rb diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 37b52b3f..078dc3b5 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 70436826..1ae5996b 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -1,6 +1,6 @@ # $Id: testldif.rb 61 2006-04-18 20:55:55Z blackhedd $ -require 'common' +require 'test_helper' require 'digest/sha1' require 'base64' diff --git a/test/test_password.rb b/test/test_password.rb index abc8c22b..3fe17364 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -1,6 +1,6 @@ # $Id: testpsw.rb 72 2006-04-24 21:58:14Z blackhedd $ -require 'common' +require 'test_helper' class TestPassword < Test::Unit::TestCase diff --git a/test/test_rename.rb b/test/test_rename.rb index db82340a..066b34ac 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -1,7 +1,7 @@ -require 'common' +require 'test_helper' # Commented out since it assumes you have a live LDAP server somewhere. This -# will be migrated to the integration specs, as soon as they are ready. +# will be migrated to the integration specs, as soon as they are ready. =begin class TestRename < Test::Unit::TestCase HOST= '10.10.10.71' diff --git a/test/test_search.rb b/test/test_search.rb index 23f1f7ff..3d9972de 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'common' +require 'test_helper' class TestSearch < Test::Unit::TestCase class FakeConnection diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 065025ed..440d4d98 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -1,6 +1,6 @@ # $Id: testsnmp.rb 231 2006-12-21 15:09:29Z blackhedd $ -require 'common' +require 'test_helper' require 'net/snmp' class TestSnmp < Test::Unit::TestCase diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index 68b48d8c..8c947b6a 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' require 'timeout' class TestSSLBER < Test::Unit::TestCase From ef6a16737e7e6a10f38b4d1900cbd5b9f817dd0b Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 12 Oct 2014 01:21:57 -0700 Subject: [PATCH 145/435] Use test_helper instead of common now --- test/test_ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ldap.rb b/test/test_ldap.rb index ac0c28d5..efcaeddf 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -1,4 +1,4 @@ -require 'common' +require 'test_helper' class TestLDAPInstrumentation < Test::Unit::TestCase def setup From 9ecdc5db48a062658ba822a2853e62196999fe0f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 12 Oct 2014 02:13:02 -0700 Subject: [PATCH 146/435] Clarify connection instrumentation test class Otherwise, we conflict with Net::LDAP instrumentation test class, causing mysterious failures. --- test/test_ldap_connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 078dc3b5..601e07b9 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -74,7 +74,7 @@ def test_no_error_on_success end end -class TestLDAPInstrumentation < Test::Unit::TestCase +class TestLDAPConnectionInstrumentation < Test::Unit::TestCase def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) From c947b89e7d95f143cb774bf4541b10c36f55bd31 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 12 Oct 2014 02:28:40 -0700 Subject: [PATCH 147/435] server -> host --- test/test_ldap_connection.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 601e07b9..0eb46b2b 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -3,14 +3,14 @@ class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host assert_raise Net::LDAP::LdapError do - Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end def test_blocked_port flexmock(TCPSocket).should_receive(:new).and_raise(SocketError) assert_raise Net::LDAP::LdapError do - Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end @@ -18,7 +18,7 @@ def test_raises_unknown_exceptions error = Class.new(StandardError) flexmock(TCPSocket).should_receive(:new).and_raise(error) assert_raise error do - Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end @@ -50,7 +50,7 @@ def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) - @connection = Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) + @connection = Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end def test_error_failed_operation @@ -82,7 +82,7 @@ def setup @service = MockInstrumentationService.new @connection = Net::LDAP::Connection.new \ - :server => 'test.mocked.com', + :host => 'test.mocked.com', :port => 636, :instrumentation_service => @service end From a84e480c8acf8f4e7c2ef3d579ec87c6277da0d2 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 12 Oct 2014 02:38:57 -0700 Subject: [PATCH 148/435] Hanlde EHOSTUNREACH error --- lib/net/ldap/connection.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 00d21502..69baa57f 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -15,6 +15,8 @@ def initialize(server) raise Net::LDAP::LdapError, "No such address or other socket error." rescue Errno::ECONNREFUSED raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." + rescue Errno::EHOSTUNREACH => error + raise Net::LDAP::LdapError, "Host #{server[:host]} was unreachable (#{error.message})" end if server[:encryption] From 1ac9d61786526cb44a1d84c24daec67588278c48 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 12 Oct 2014 02:39:08 -0700 Subject: [PATCH 149/435] Another server -> host change --- test/test_ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ldap.rb b/test/test_ldap.rb index efcaeddf..5984aba7 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -7,7 +7,7 @@ def setup @service = MockInstrumentationService.new @subject = Net::LDAP.new \ - :server => "test.mocked.com", :port => 636, + :host => "test.mocked.com", :port => 636, :force_no_page => true, # so server capabilities are not queried :instrumentation_service => @service end From 286ace6f05856eb0b94fe4be492f36649dccdfab Mon Sep 17 00:00:00 2001 From: Mattias Ohlsson Date: Tue, 1 Jul 2014 09:58:55 +0200 Subject: [PATCH 150/435] handle base64 encoded dn attr --- lib/net/ldap/dataset.rb | 6 ++++-- test/test_ldif.rb | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/dataset.rb b/lib/net/ldap/dataset.rb index 9f3c46fe..79431e8d 100644 --- a/lib/net/ldap/dataset.rb +++ b/lib/net/ldap/dataset.rb @@ -136,8 +136,10 @@ def read_ldif(io) elsif line =~ /^version:[\s]*([0-9]+)$/i ds.version = $1 yield :version, line if block_given? - elsif line =~ /^dn:[\s]*/i - dn = $' + elsif line =~ /^dn:([\:]?)[\s]*/i + # $1 is a colon if the dn-value is base-64 encoded + # $' is the dn-value + dn = ($1 == ":") ? $'.unpack('m').shift : $' ds[dn] = Hash.new { |k,v| k[v] = [] } yield :dn, dn if block_given? elsif line.empty? diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 70436826..eb9dfd32 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -53,6 +53,18 @@ def test_ldif_tab_is_not_continuation assert_equal(true, ds.has_key?("key")) end + def test_ldif_with_base64_dn + str = "dn:: Q049QmFzZTY0IGRuIHRlc3QsT1U9VGVzdCxPVT1Vbml0cyxEQz1leGFtcGxlLERDPWNvbQ==\r\n\r\n" + ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) + assert_equal(true, ds.has_key?("CN=Base64 dn test,OU=Test,OU=Units,DC=example,DC=com")) + end + + def test_ldif_with_base64_dn_and_continuation_lines + str = "dn:: Q049QmFzZTY0IGRuIHRlc3Qgd2l0aCBjb250aW51YXRpb24gbGluZSxPVT1UZXN0LE9VPVVua\r\n XRzLERDPWV4YW1wbGUsREM9Y29t\r\n\r\n" + ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) + assert_equal(true, ds.has_key?("CN=Base64 dn test with continuation line,OU=Test,OU=Units,DC=example,DC=com")) + end + # TODO, INADEQUATE. We need some more tests # to verify the content. def test_ldif From 223797095c519d18248526af2a184d223c79d8b7 Mon Sep 17 00:00:00 2001 From: Mattias Ohlsson Date: Sun, 12 Oct 2014 13:52:29 +0200 Subject: [PATCH 151/435] Explain why we are using unpack --- lib/net/ldap/dataset.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap/dataset.rb b/lib/net/ldap/dataset.rb index 79431e8d..54fc1a07 100644 --- a/lib/net/ldap/dataset.rb +++ b/lib/net/ldap/dataset.rb @@ -139,6 +139,7 @@ def read_ldif(io) elsif line =~ /^dn:([\:]?)[\s]*/i # $1 is a colon if the dn-value is base-64 encoded # $' is the dn-value + # Avoid the Base64 class because not all Ruby versions have it. dn = ($1 == ":") ? $'.unpack('m').shift : $' ds[dn] = Hash.new { |k,v| k[v] = [] } yield :dn, dn if block_given? From da8eebcca3fd1f66ec8306e8ae511694dcbaea54 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 15:10:27 -0700 Subject: [PATCH 152/435] generate files to include in gem automatically --- net-ldap.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 854d4c6e..1414cc8d 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -24,7 +24,7 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/instrumentation.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"] + s.files = `git ls-files`.split $/ s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] From 3e061e24e06e6e53e4d47c90cc237acc247efc87 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:10:39 -0700 Subject: [PATCH 153/435] reference discussion comment --- test/test_ssl_ber.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index 8c947b6a..d41a8a92 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -19,6 +19,9 @@ def setup # The production code operates on sockets, which do need #connect called # on them to work. Pipes are more robust for this test, so we'll skip # the #connect call since it fails. + # + # TODO: Replace test with real socket + # https://github.com/ruby-ldap/ruby-net-ldap/pull/121#discussion_r18746386 flexmock(OpenSSL::SSL::SSLSocket). new_instances.should_receive(:connect => nil) From 36005eb9e2d257b30149be65c5f02234245ed66c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:14:25 -0700 Subject: [PATCH 154/435] require_relative test_helper --- test/ber/core_ext/test_array.rb | 2 +- test/ber/core_ext/test_string.rb | 2 +- test/ber/test_ber.rb | 2 +- test/test_dn.rb | 2 +- test/test_entry.rb | 2 +- test/test_filter.rb | 2 +- test/test_filter_parser.rb | 2 +- test/test_ldap_connection.rb | 2 +- test/test_ldif.rb | 2 +- test/test_password.rb | 2 +- test/test_rename.rb | 2 +- test/test_search.rb | 2 +- test/test_snmp.rb | 2 +- test/test_ssl_ber.rb | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index cba9ea7a..308fffc5 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../../test_helper' class TestBERArrayExtension < Test::Unit::TestCase def test_control_code_array diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index 95ece554..692770e4 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../../test_helper' class TestBERStringExtension < Test::Unit::TestCase def setup diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 97bcf129..eb5c1848 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' class TestBEREncoding < Test::Unit::TestCase def test_empty_array diff --git a/test/test_dn.rb b/test/test_dn.rb index b758b913..8ca2f76c 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' require 'net/ldap/dn' class TestDN < Test::Unit::TestCase diff --git a/test/test_entry.rb b/test/test_entry.rb index 90752c00..55b7b83f 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' class TestEntry < Test::Unit::TestCase def setup diff --git a/test/test_filter.rb b/test/test_filter.rb index 62db542b..bf125e4a 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' class TestFilter < Test::Unit::TestCase Filter = Net::LDAP::Filter diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index ded4a026..7620f5ec 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require 'test_helper' +require_relative '../test_helper' class TestFilterParser < Test::Unit::TestCase def test_ascii diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 078dc3b5..8d098980 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 1ae5996b..8736978f 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -1,6 +1,6 @@ # $Id: testldif.rb 61 2006-04-18 20:55:55Z blackhedd $ -require 'test_helper' +require_relative '../test_helper' require 'digest/sha1' require 'base64' diff --git a/test/test_password.rb b/test/test_password.rb index 3fe17364..ec4c46e6 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -1,6 +1,6 @@ # $Id: testpsw.rb 72 2006-04-24 21:58:14Z blackhedd $ -require 'test_helper' +require_relative '../test_helper' class TestPassword < Test::Unit::TestCase diff --git a/test/test_rename.rb b/test/test_rename.rb index 066b34ac..8992b5d5 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' # Commented out since it assumes you have a live LDAP server somewhere. This # will be migrated to the integration specs, as soon as they are ready. diff --git a/test/test_search.rb b/test/test_search.rb index 3d9972de..025e88ea 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'test_helper' +require_relative '../test_helper' class TestSearch < Test::Unit::TestCase class FakeConnection diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 440d4d98..18ddcf06 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -1,6 +1,6 @@ # $Id: testsnmp.rb 231 2006-12-21 15:09:29Z blackhedd $ -require 'test_helper' +require_relative '../test_helper' require 'net/snmp' class TestSnmp < Test::Unit::TestCase diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index d41a8a92..cca8a898 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../test_helper' require 'timeout' class TestSSLBER < Test::Unit::TestCase From 4866778808e320aa58a717423fcf0a21d259a35a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:18:06 -0700 Subject: [PATCH 155/435] update gitignore - gemspec is useful information - coverage isn't run anymore - more aggressive blob for emacs and vim backup files --- .gitignore | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 1959fc00..cedadc26 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,7 @@ -spec/ldap.yml +*~ +*.swp .rvmrc -*.gemspec pkg/ -*.swp -html/ doc/ publish/ -coverage/ -coverage.info -.rake_tasks~ Gemfile.lock From 11682152ba8032b7818dcf763c7cb621e3af8754 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:23:15 -0700 Subject: [PATCH 156/435] use Minitest::Test --- Gemfile | 4 ++++ test/ber/core_ext/test_array.rb | 2 +- test/ber/core_ext/test_string.rb | 2 +- test/ber/test_ber.rb | 6 +++--- test/test_dn.rb | 2 +- test/test_entry.rb | 4 ++-- test/test_filter.rb | 4 ++-- test/test_filter_parser.rb | 2 +- test/test_ldap_connection.rb | 6 +++--- test/test_ldif.rb | 2 +- test/test_password.rb | 2 +- test/test_rename.rb | 2 +- test/test_search.rb | 2 +- test/test_snmp.rb | 2 +- test/test_ssl_ber.rb | 2 +- 15 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Gemfile b/Gemfile index 851fabc2..bc78e7e6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,6 @@ source 'https://rubygems.org' gemspec + +group :test do + gem "minitest", "~> 5.0" +end diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index 308fffc5..038bed13 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -1,6 +1,6 @@ require_relative '../../test_helper' -class TestBERArrayExtension < Test::Unit::TestCase +class TestBERArrayExtension < Minitest::Test def test_control_code_array control_codes = [] control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index 692770e4..56b3a4aa 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -1,6 +1,6 @@ require_relative '../../test_helper' -class TestBERStringExtension < Test::Unit::TestCase +class TestBERStringExtension < Minitest::Test def setup @bind_request = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED".b @result = @bind_request.read_ber!(Net::LDAP::AsnSyntax) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index eb5c1848..3ee9e5cd 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestBEREncoding < Test::Unit::TestCase +class TestBEREncoding < Minitest::Test def test_empty_array assert_equal [], [].to_ber.read_ber end @@ -84,7 +84,7 @@ def test_non_utf8_encodable_strings end end -class TestBERDecoding < Test::Unit::TestCase +class TestBERDecoding < Minitest::Test def test_decode_number assert_equal 6, "\002\001\006".read_ber(Net::LDAP::AsnSyntax) end @@ -98,7 +98,7 @@ def test_decode_ldap_bind_request end end -class TestBERIdentifiedString < Test::Unit::TestCase +class TestBERIdentifiedString < Minitest::Test def test_binary_data data = ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") bis = Net::BER::BerIdentifiedString.new(data) diff --git a/test/test_dn.rb b/test/test_dn.rb index 8ca2f76c..193c6e0a 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'net/ldap/dn' -class TestDN < Test::Unit::TestCase +class TestDN < Minitest::Test def test_escape assert_equal '\\,\\+\\"\\\\\\<\\>\\;', Net::LDAP::DN.escape(',+"\\<>;') end diff --git a/test/test_entry.rb b/test/test_entry.rb index 55b7b83f..65fbe026 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestEntry < Test::Unit::TestCase +class TestEntry < Minitest::Test def setup @entry = Net::LDAP::Entry.new 'cn=Barbara,o=corp' end @@ -41,7 +41,7 @@ def test_case_insensitive_attribute_names end end -class TestEntryLDIF < Test::Unit::TestCase +class TestEntryLDIF < Minitest::Test def setup @entry = Net::LDAP::Entry.from_single_ldif_string( %Q{dn: something diff --git a/test/test_filter.rb b/test/test_filter.rb index bf125e4a..5ba39ad2 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestFilter < Test::Unit::TestCase +class TestFilter < Minitest::Test Filter = Net::LDAP::Filter def test_bug_7534_rfc2254 @@ -123,7 +123,7 @@ def test_ber_from_rfc2254_filter # tests ported over from rspec. Not sure if these overlap with the above # https://github.com/ruby-ldap/ruby-net-ldap/pull/121 -class TestFilterRSpec < Test::Unit::TestCase +class TestFilterRSpec < Minitest::Test def test_ex_convert assert_equal '(foo:=bar)', Net::LDAP::Filter.ex('foo', 'bar').to_s end diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 7620f5ec..71415539 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require_relative '../test_helper' -class TestFilterParser < Test::Unit::TestCase +class TestFilterParser < Minitest::Test def test_ascii assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=name)") end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 2cf3d392..e157e21b 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestLDAPConnection < Test::Unit::TestCase +class TestLDAPConnection < Minitest::Test def test_unresponsive_host assert_raise Net::LDAP::LdapError do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) @@ -45,7 +45,7 @@ def test_modify_ops_replace end -class TestLDAPConnectionErrors < Test::Unit::TestCase +class TestLDAPConnectionErrors < Minitest::Test def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) @@ -74,7 +74,7 @@ def test_no_error_on_success end end -class TestLDAPConnectionInstrumentation < Test::Unit::TestCase +class TestLDAPConnectionInstrumentation < Minitest::Test def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 8736978f..87aa453d 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -5,7 +5,7 @@ require 'digest/sha1' require 'base64' -class TestLdif < Test::Unit::TestCase +class TestLdif < Minitest::Test TestLdifFilename = "#{File.dirname(__FILE__)}/testdata.ldif" def test_empty_ldif diff --git a/test/test_password.rb b/test/test_password.rb index ec4c46e6..263e89a0 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -2,7 +2,7 @@ require_relative '../test_helper' -class TestPassword < Test::Unit::TestCase +class TestPassword < Minitest::Test def test_psw assert_equal( diff --git a/test/test_rename.rb b/test/test_rename.rb index 8992b5d5..282ec429 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -3,7 +3,7 @@ # Commented out since it assumes you have a live LDAP server somewhere. This # will be migrated to the integration specs, as soon as they are ready. =begin -class TestRename < Test::Unit::TestCase +class TestRename < Minitest::Test HOST= '10.10.10.71' PORT = 389 BASE = "o=test" diff --git a/test/test_search.rb b/test/test_search.rb index 025e88ea..9d2bd7b1 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,7 +1,7 @@ # -*- ruby encoding: utf-8 -*- require_relative '../test_helper' -class TestSearch < Test::Unit::TestCase +class TestSearch < Minitest::Test class FakeConnection def search(args) OpenStruct.new(:result_code => 1, :message => "error", :success? => false) diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 18ddcf06..4746a5a7 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -3,7 +3,7 @@ require_relative '../test_helper' require 'net/snmp' -class TestSnmp < Test::Unit::TestCase +class TestSnmp < Minitest::Test def self.raw_string(s) # Conveniently, String#b only needs to be called when it exists s.respond_to?(:b) ? s.b : s diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index cca8a898..5ff2542d 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'timeout' -class TestSSLBER < Test::Unit::TestCase +class TestSSLBER < Minitest::Test # Transmits str to @to and reads it back from @from. # def transmit(str) From 20f20f882c14135e0c90159fd32aad529e92ddcc Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:38:44 -0700 Subject: [PATCH 157/435] Revert "use Minitest::Test" This reverts commit 11682152ba8032b7818dcf763c7cb621e3af8754. https://github.com/ruby-ldap/ruby-net-ldap/pull/121#issuecomment-58970363 --- Gemfile | 4 ---- test/ber/core_ext/test_array.rb | 2 +- test/ber/core_ext/test_string.rb | 2 +- test/ber/test_ber.rb | 6 +++--- test/test_dn.rb | 2 +- test/test_entry.rb | 4 ++-- test/test_filter.rb | 4 ++-- test/test_filter_parser.rb | 2 +- test/test_ldap_connection.rb | 6 +++--- test/test_ldif.rb | 2 +- test/test_password.rb | 2 +- test/test_rename.rb | 2 +- test/test_search.rb | 2 +- test/test_snmp.rb | 2 +- test/test_ssl_ber.rb | 2 +- 15 files changed, 20 insertions(+), 24 deletions(-) diff --git a/Gemfile b/Gemfile index bc78e7e6..851fabc2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,2 @@ source 'https://rubygems.org' gemspec - -group :test do - gem "minitest", "~> 5.0" -end diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index 038bed13..308fffc5 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -1,6 +1,6 @@ require_relative '../../test_helper' -class TestBERArrayExtension < Minitest::Test +class TestBERArrayExtension < Test::Unit::TestCase def test_control_code_array control_codes = [] control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence diff --git a/test/ber/core_ext/test_string.rb b/test/ber/core_ext/test_string.rb index 56b3a4aa..692770e4 100644 --- a/test/ber/core_ext/test_string.rb +++ b/test/ber/core_ext/test_string.rb @@ -1,6 +1,6 @@ require_relative '../../test_helper' -class TestBERStringExtension < Minitest::Test +class TestBERStringExtension < Test::Unit::TestCase def setup @bind_request = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED".b @result = @bind_request.read_ber!(Net::LDAP::AsnSyntax) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 3ee9e5cd..eb5c1848 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestBEREncoding < Minitest::Test +class TestBEREncoding < Test::Unit::TestCase def test_empty_array assert_equal [], [].to_ber.read_ber end @@ -84,7 +84,7 @@ def test_non_utf8_encodable_strings end end -class TestBERDecoding < Minitest::Test +class TestBERDecoding < Test::Unit::TestCase def test_decode_number assert_equal 6, "\002\001\006".read_ber(Net::LDAP::AsnSyntax) end @@ -98,7 +98,7 @@ def test_decode_ldap_bind_request end end -class TestBERIdentifiedString < Minitest::Test +class TestBERIdentifiedString < Test::Unit::TestCase def test_binary_data data = ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") bis = Net::BER::BerIdentifiedString.new(data) diff --git a/test/test_dn.rb b/test/test_dn.rb index 193c6e0a..8ca2f76c 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'net/ldap/dn' -class TestDN < Minitest::Test +class TestDN < Test::Unit::TestCase def test_escape assert_equal '\\,\\+\\"\\\\\\<\\>\\;', Net::LDAP::DN.escape(',+"\\<>;') end diff --git a/test/test_entry.rb b/test/test_entry.rb index 65fbe026..55b7b83f 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestEntry < Minitest::Test +class TestEntry < Test::Unit::TestCase def setup @entry = Net::LDAP::Entry.new 'cn=Barbara,o=corp' end @@ -41,7 +41,7 @@ def test_case_insensitive_attribute_names end end -class TestEntryLDIF < Minitest::Test +class TestEntryLDIF < Test::Unit::TestCase def setup @entry = Net::LDAP::Entry.from_single_ldif_string( %Q{dn: something diff --git a/test/test_filter.rb b/test/test_filter.rb index 5ba39ad2..bf125e4a 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestFilter < Minitest::Test +class TestFilter < Test::Unit::TestCase Filter = Net::LDAP::Filter def test_bug_7534_rfc2254 @@ -123,7 +123,7 @@ def test_ber_from_rfc2254_filter # tests ported over from rspec. Not sure if these overlap with the above # https://github.com/ruby-ldap/ruby-net-ldap/pull/121 -class TestFilterRSpec < Minitest::Test +class TestFilterRSpec < Test::Unit::TestCase def test_ex_convert assert_equal '(foo:=bar)', Net::LDAP::Filter.ex('foo', 'bar').to_s end diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 71415539..7620f5ec 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require_relative '../test_helper' -class TestFilterParser < Minitest::Test +class TestFilterParser < Test::Unit::TestCase def test_ascii assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=name)") end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index e157e21b..2cf3d392 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class TestLDAPConnection < Minitest::Test +class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host assert_raise Net::LDAP::LdapError do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) @@ -45,7 +45,7 @@ def test_modify_ops_replace end -class TestLDAPConnectionErrors < Minitest::Test +class TestLDAPConnectionErrors < Test::Unit::TestCase def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) @@ -74,7 +74,7 @@ def test_no_error_on_success end end -class TestLDAPConnectionInstrumentation < Minitest::Test +class TestLDAPConnectionInstrumentation < Test::Unit::TestCase def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) diff --git a/test/test_ldif.rb b/test/test_ldif.rb index eb15c575..bcb90862 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -5,7 +5,7 @@ require 'digest/sha1' require 'base64' -class TestLdif < Minitest::Test +class TestLdif < Test::Unit::TestCase TestLdifFilename = "#{File.dirname(__FILE__)}/testdata.ldif" def test_empty_ldif diff --git a/test/test_password.rb b/test/test_password.rb index 263e89a0..ec4c46e6 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -2,7 +2,7 @@ require_relative '../test_helper' -class TestPassword < Minitest::Test +class TestPassword < Test::Unit::TestCase def test_psw assert_equal( diff --git a/test/test_rename.rb b/test/test_rename.rb index 282ec429..8992b5d5 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -3,7 +3,7 @@ # Commented out since it assumes you have a live LDAP server somewhere. This # will be migrated to the integration specs, as soon as they are ready. =begin -class TestRename < Minitest::Test +class TestRename < Test::Unit::TestCase HOST= '10.10.10.71' PORT = 389 BASE = "o=test" diff --git a/test/test_search.rb b/test/test_search.rb index 9d2bd7b1..025e88ea 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,7 +1,7 @@ # -*- ruby encoding: utf-8 -*- require_relative '../test_helper' -class TestSearch < Minitest::Test +class TestSearch < Test::Unit::TestCase class FakeConnection def search(args) OpenStruct.new(:result_code => 1, :message => "error", :success? => false) diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 4746a5a7..18ddcf06 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -3,7 +3,7 @@ require_relative '../test_helper' require 'net/snmp' -class TestSnmp < Minitest::Test +class TestSnmp < Test::Unit::TestCase def self.raw_string(s) # Conveniently, String#b only needs to be called when it exists s.respond_to?(:b) ? s.b : s diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index 5ff2542d..cca8a898 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'timeout' -class TestSSLBER < Minitest::Test +class TestSSLBER < Test::Unit::TestCase # Transmits str to @to and reads it back from @from. # def transmit(str) From 5fd46beb5aac4347486a9cf8806cfaaae4422781 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:41:01 -0700 Subject: [PATCH 158/435] oops, wrong nesting --- test/ber/test_ber.rb | 2 +- test/test_dn.rb | 2 +- test/test_entry.rb | 2 +- test/test_filter.rb | 2 +- test/test_filter_parser.rb | 2 +- test/test_ldap_connection.rb | 2 +- test/test_ldif.rb | 2 +- test/test_password.rb | 2 +- test/test_rename.rb | 2 +- test/test_search.rb | 2 +- test/test_snmp.rb | 2 +- test/test_ssl_ber.rb | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index eb5c1848..35580210 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' class TestBEREncoding < Test::Unit::TestCase def test_empty_array diff --git a/test/test_dn.rb b/test/test_dn.rb index 8ca2f76c..0cb2ec5a 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' require 'net/ldap/dn' class TestDN < Test::Unit::TestCase diff --git a/test/test_entry.rb b/test/test_entry.rb index 55b7b83f..e2184747 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' class TestEntry < Test::Unit::TestCase def setup diff --git a/test/test_filter.rb b/test/test_filter.rb index bf125e4a..eb6192d0 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' class TestFilter < Test::Unit::TestCase Filter = Net::LDAP::Filter diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 7620f5ec..8fdab389 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require_relative '../test_helper' +require_relative 'test_helper' class TestFilterParser < Test::Unit::TestCase def test_ascii diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 2cf3d392..bf2a865a 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host diff --git a/test/test_ldif.rb b/test/test_ldif.rb index bcb90862..988c3155 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -1,6 +1,6 @@ # $Id: testldif.rb 61 2006-04-18 20:55:55Z blackhedd $ -require_relative '../test_helper' +require_relative 'test_helper' require 'digest/sha1' require 'base64' diff --git a/test/test_password.rb b/test/test_password.rb index ec4c46e6..26ed54af 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -1,6 +1,6 @@ # $Id: testpsw.rb 72 2006-04-24 21:58:14Z blackhedd $ -require_relative '../test_helper' +require_relative 'test_helper' class TestPassword < Test::Unit::TestCase diff --git a/test/test_rename.rb b/test/test_rename.rb index 8992b5d5..6e6ee65a 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' # Commented out since it assumes you have a live LDAP server somewhere. This # will be migrated to the integration specs, as soon as they are ready. diff --git a/test/test_search.rb b/test/test_search.rb index 025e88ea..1481aa06 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require_relative '../test_helper' +require_relative 'test_helper' class TestSearch < Test::Unit::TestCase class FakeConnection diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 18ddcf06..fe1ee168 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -1,6 +1,6 @@ # $Id: testsnmp.rb 231 2006-12-21 15:09:29Z blackhedd $ -require_relative '../test_helper' +require_relative 'test_helper' require 'net/snmp' class TestSnmp < Test::Unit::TestCase diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index cca8a898..7711558b 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -1,4 +1,4 @@ -require_relative '../test_helper' +require_relative 'test_helper' require 'timeout' class TestSSLBER < Test::Unit::TestCase From 27bd182d4a86767dce9c79cc7e986c37581b5900 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 13 Oct 2014 16:49:42 -0700 Subject: [PATCH 159/435] missed a spot --- test/ber/test_ber.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 35580210..eb5c1848 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -1,4 +1,4 @@ -require_relative 'test_helper' +require_relative '../test_helper' class TestBEREncoding < Test::Unit::TestCase def test_empty_array From 7a4dda57edc4debc3aff698ed90065243a38ca73 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 20:42:01 -0700 Subject: [PATCH 160/435] Switch to assert from assert_predicate --- test/ber/test_ber.rb | 6 +++--- test/test_ldap_connection.rb | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index eb5c1848..6f641bb4 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -103,7 +103,7 @@ def test_binary_data data = ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") bis = Net::BER::BerIdentifiedString.new(data) - assert_predicate bis, :valid_encoding? + assert bis.valid_encoding?, "should be a valid encoding" assert_equal "ASCII-8BIT", bis.encoding.name end @@ -111,7 +111,7 @@ def test_ascii_data_in_utf8 data = "some text".force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) - assert_predicate bis, :valid_encoding? + assert bis.valid_encoding?, "should be a valid encoding" assert_equal "UTF-8", bis.encoding.name end @@ -119,7 +119,7 @@ def test_ut8_data_in_utf8 data = ["e4b8ad"].pack("H*").force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) - assert_predicate bis, :valid_encoding? + assert bis.valid_encoding?, "should be a valid encoding" assert_equal "UTF-8", bis.encoding.name end end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index bf2a865a..d62c5992 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -59,7 +59,7 @@ def test_error_failed_operation @tcp_socket.should_receive(:read_ber).and_return([2, ber]) result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) - assert_predicate result, :failure? + assert result.failure?, "should be failure" 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 end @@ -69,7 +69,7 @@ def test_no_error_on_success @tcp_socket.should_receive(:read_ber).and_return([2, ber]) result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) - assert_predicate result, :success? + assert result.success?, "should be success" assert_equal "", result.error_message end end @@ -96,7 +96,7 @@ def test_write_net_ldap_connection_event events = @service.subscribe "write.net_ldap_connection" result = @connection.bind(method: :anon) - assert_predicate result, :success? + assert result.success?, "should be success" # a write event payload, result = events.pop @@ -113,7 +113,7 @@ def test_read_net_ldap_connection_event events = @service.subscribe "read.net_ldap_connection" result = @connection.bind(method: :anon) - assert_predicate result, :success? + assert result.success?, "should be success" # a read event payload, result = events.pop @@ -130,12 +130,12 @@ def test_bind_net_ldap_connection_event events = @service.subscribe "bind.net_ldap_connection" result = @connection.bind(method: :anon) - assert_predicate result, :success? + assert result.success?, "should be success" # a read event payload, result = events.pop assert payload.has_key?(:result) - assert_predicate result, :success? + assert result.success?, "should be success" end def test_search_net_ldap_connection_event @@ -156,7 +156,7 @@ def test_search_net_ldap_connection_event events = @service.subscribe "search.net_ldap_connection" result = @connection.search(filter: "(uid=user1)") - assert_predicate result, :success? + assert result.success?, "should be success" # a search event payload, result = events.pop From a68622937e62ca96060304789982bffd9d0cfe70 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 20:55:56 -0700 Subject: [PATCH 161/435] Stub out String#b for Ruby 1.9 --- test/test_helper.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index eea28c24..b25aea7c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -3,6 +3,14 @@ require 'net/ldap' require 'flexmock/test_unit' +if RUBY_VERSION < "2.0" + class String + def b + self + end + end +end + class MockInstrumentationService def initialize @events = {} From eda12bbe6737ab369b12f19d92b0f1749bcd1357 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 22:41:19 -0700 Subject: [PATCH 162/435] Add integration test with OpenLDAP to Travis matrix --- .travis.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4dd7b6dc..2ea9922e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,18 @@ rvm: - jruby-19mode - rbx-19mode # - rbx-2 + +env: + - INTEGRATION=skip + - INTEGRATION=openldap + +install: + - if [ "$INTEGRATION" = "openldap" ]; then ./script/install-openldap; fi + - bundle install + +script: bundle exec rake + matrix: allow_failures: - rvm: jruby-19mode -script: bundle exec rake + fast_finish: true From 9ee27302a1f3785a02ce4e19323260fc189e3b0b Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 22:41:50 -0700 Subject: [PATCH 163/435] Add INTEGRATION flag constant --- test/test_helper.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index b25aea7c..70d4b70d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -3,6 +3,9 @@ require 'net/ldap' require 'flexmock/test_unit' +# Whether integration tests should be run. +INTEGRATION = ENV.fetch("INTEGRATION", "skip") != "skip" + if RUBY_VERSION < "2.0" class String def b From 0abd796067dd1da96359095b93f00849f75e4a27 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 22:42:34 -0700 Subject: [PATCH 164/435] Add OpenLDAP installer, seed/config fixtures --- script/install-openldap | 44 +++ test/fixtures/openldap/memberof.ldif | 33 +++ test/fixtures/openldap/slapd.conf.ldif | 67 +++++ test/fixtures/seed.ldif | 374 +++++++++++++++++++++++++ 4 files changed, 518 insertions(+) create mode 100755 script/install-openldap create mode 100644 test/fixtures/openldap/memberof.ldif create mode 100644 test/fixtures/openldap/slapd.conf.ldif create mode 100644 test/fixtures/seed.ldif diff --git a/script/install-openldap b/script/install-openldap new file mode 100755 index 00000000..cd9491c1 --- /dev/null +++ b/script/install-openldap @@ -0,0 +1,44 @@ +#!/usr/bin/env sh +set -e +set -x + +BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" +SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" + +DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils + +sudo /etc/init.d/slapd stop + +TMPDIR=$(mktemp -d) +cd $TMPDIR + +# Delete data and reconfigure. +sudo cp -v /var/lib/ldap/DB_CONFIG ./DB_CONFIG +sudo rm -rf /etc/ldap/slapd.d/* +sudo rm -rf /var/lib/ldap/* +sudo cp -v ./DB_CONFIG /var/lib/ldap/DB_CONFIG +sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/slapd.conf.ldif +# Load memberof and ref-int overlays and configure them. +sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/memberof.ldif + +# Add base domain. +sudo slapadd -F /etc/ldap/slapd.d < Date: Mon, 13 Oct 2014 23:19:03 -0700 Subject: [PATCH 165/435] Add basic integration tests for bind --- test/test_integration.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/test_integration.rb diff --git a/test/test_integration.rb b/test/test_integration.rb new file mode 100644 index 00000000..c4fee0bc --- /dev/null +++ b/test/test_integration.rb @@ -0,0 +1,31 @@ +require_relative 'test_helper' + +if !INTEGRATION + puts "Skipping integration tests..." +else + class TestLDAPInstrumentation < Test::Unit::TestCase + def setup + @service = MockInstrumentationService.new + @ldap = Net::LDAP.new \ + host: 'localhost', + port: 389, + admin_user: 'uid=admin,dc=rubyldap,dc=com', + admin_password: 'passworD1', + search_domains: %w(dc=rubyldap,dc=com), + uid: 'uid', + instrumentation_service: @service + end + + def test_bind_success + assert @ldap.bind(method: :simple, username: "user1", password: "passworD1") + end + + def test_bind_success_anonymous + assert @ldap.bind(method: :simple, username: "user1", password: "") + end + + def test_bind_fail + refute @ldap.bind(method: :simple, username: "user1", password: "not my password") + end + end +end From 415dd9d6d730ba3915e21bef95fb5caab123c319 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:22:08 -0700 Subject: [PATCH 166/435] Fix test class name --- test/test_integration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index c4fee0bc..76a9cd74 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -3,7 +3,7 @@ if !INTEGRATION puts "Skipping integration tests..." else - class TestLDAPInstrumentation < Test::Unit::TestCase + class TestLDAPIntegration < Test::Unit::TestCase def setup @service = MockInstrumentationService.new @ldap = Net::LDAP.new \ From 1ebd71aeb69886f972168ff3d2dd4f3470596bbb Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:26:19 -0700 Subject: [PATCH 167/435] No email notifications for CI builds --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2ea9922e..20946629 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,3 +21,6 @@ matrix: allow_failures: - rvm: jruby-19mode fast_finish: true + +notifications: + email: false From 66dc72f9f8a4d41244df8a6e9bdbeb4ff3591056 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:27:34 -0700 Subject: [PATCH 168/435] Show operation result for failed binds --- test/test_integration.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index 76a9cd74..ba7e01d7 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -17,15 +17,15 @@ def setup end def test_bind_success - assert @ldap.bind(method: :simple, username: "user1", password: "passworD1") + assert @ldap.bind(method: :simple, username: "user1", password: "passworD1"), @ldap.get_operation_result end def test_bind_success_anonymous - assert @ldap.bind(method: :simple, username: "user1", password: "") + assert @ldap.bind(method: :simple, username: "user1", password: ""), @ldap.get_operation_result end def test_bind_fail - refute @ldap.bind(method: :simple, username: "user1", password: "not my password") + refute @ldap.bind(method: :simple, username: "user1", password: "not my password"), @ldap.get_operation_result end end end From 05133c12fb414824fadbb5f73a8bc0719b5f02dd Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:29:25 -0700 Subject: [PATCH 169/435] Inspect the operation result struct for details --- test/test_integration.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index ba7e01d7..aa0a5577 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -17,15 +17,15 @@ def setup end def test_bind_success - assert @ldap.bind(method: :simple, username: "user1", password: "passworD1"), @ldap.get_operation_result + assert @ldap.bind(method: :simple, username: "user1", password: "passworD1"), @ldap.get_operation_result.inspect end def test_bind_success_anonymous - assert @ldap.bind(method: :simple, username: "user1", password: ""), @ldap.get_operation_result + assert @ldap.bind(method: :simple, username: "user1", password: ""), @ldap.get_operation_result.inspect end def test_bind_fail - refute @ldap.bind(method: :simple, username: "user1", password: "not my password"), @ldap.get_operation_result + refute @ldap.bind(method: :simple, username: "user1", password: "not my password"), @ldap.get_operation_result.inspect end end end From a1978ebf6c09189081f2d0f9e76826771fc90699 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:32:55 -0700 Subject: [PATCH 170/435] Bind with full DN --- test/test_integration.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index aa0a5577..0922088c 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -17,15 +17,15 @@ def setup end def test_bind_success - assert @ldap.bind(method: :simple, username: "user1", password: "passworD1"), @ldap.get_operation_result.inspect + assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end def test_bind_success_anonymous - assert @ldap.bind(method: :simple, username: "user1", password: ""), @ldap.get_operation_result.inspect + assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect end def test_bind_fail - refute @ldap.bind(method: :simple, username: "user1", password: "not my password"), @ldap.get_operation_result.inspect + refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect end end end From cb5f0ef0d2ec3a510b3489d0cf2f14a88a45be79 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 13 Oct 2014 23:38:39 -0700 Subject: [PATCH 171/435] Expect anonymous auth to fail --- test/test_integration.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index 0922088c..58e5468f 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -20,8 +20,15 @@ def test_bind_success assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end - def test_bind_success_anonymous - assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect + def test_bind_anonymous_fail + refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect + + result = @ldap.get_operation_result + assert_equal 53, result.code + assert_equal "Unwilling to perform", result.message + assert_equal "unauthenticated bind (DN with no password) disallowed", + result.error_message + assert_equal "", result.matched_dn end def test_bind_fail From 88f606612d194f6e691fbf9b36837131758066fc Mon Sep 17 00:00:00 2001 From: Nolan Date: Tue, 14 Oct 2014 09:54:53 -0700 Subject: [PATCH 172/435] replace tabs with double spaces --- Rakefile | 2 +- lib/net/ber/core_ext/string.rb | 14 +- lib/net/ldap.rb | 12 +- lib/net/ldap/password.rb | 22 +- lib/net/snmp.rb | 476 ++++++++++++++++----------------- spec/unit/ber/ber_spec.rb | 22 +- test/test_entry.rb | 2 +- test/test_filter.rb | 2 +- test/test_password.rb | 11 +- 9 files changed, 274 insertions(+), 289 deletions(-) diff --git a/Rakefile b/Rakefile index 159a8a09..3ba1345c 100644 --- a/Rakefile +++ b/Rakefile @@ -70,7 +70,7 @@ namespace :old do end end -desc "Run a full set of integration and unit tests" +desc "Run a full set of integration and unit tests" task :cruise => [:test, :spec] # vim: syntax=ruby diff --git a/lib/net/ber/core_ext/string.rb b/lib/net/ber/core_ext/string.rb index b4ad8039..e8a43e2c 100644 --- a/lib/net/ber/core_ext/string.rb +++ b/lib/net/ber/core_ext/string.rb @@ -16,13 +16,13 @@ def to_ber(code = 0x04) [code].pack('C') + raw_string.length.to_ber_length_encoding + raw_string end - ## - # Converts a string to a BER string but does *not* encode to UTF-8 first. - # This is required for proper representation of binary data for Microsoft - # Active Directory - def to_ber_bin(code = 0x04) - [code].pack('C') + length.to_ber_length_encoding + self - end + ## + # Converts a string to a BER string but does *not* encode to UTF-8 first. + # This is required for proper representation of binary data for Microsoft + # Active Directory + def to_ber_bin(code = 0x04) + [code].pack('C') + length.to_ber_length_encoding + self + end def raw_utf8_encoded if self.respond_to?(:encode) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index cbd7917c..d4d919c8 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -317,7 +317,7 @@ class LdapError < StandardError; end DefaultPort = 389 DefaultAuth = { :method => :anonymous } DefaultTreebase = "dc=com" - DefaultForceNoPage = false + DefaultForceNoPage = false StartTlsOid = "1.3.6.1.4.1.1466.20037" @@ -398,7 +398,7 @@ def initialize(args = {}) @verbose = false # Make this configurable with a switch on the class. @auth = args[:auth] || DefaultAuth @base = args[:base] || DefaultTreebase - @force_no_page = args[:force_no_page] || DefaultForceNoPage + @force_no_page = args[:force_no_page] || DefaultForceNoPage encryption args[:encryption] # may be nil if pr = @auth[:password] and pr.respond_to?(:call) @@ -1168,10 +1168,10 @@ def search_subschema_entry # MUST refactor the root_dse call out. #++ def paged_searches_supported? - # active directory returns that it supports paged results. However - # it returns binary data in the rfc2696_cookie which throws an - # encoding exception breaking searching. - return false if @force_no_page + # active directory returns that it supports paged results. However + # it returns binary data in the rfc2696_cookie which throws an + # encoding exception breaking searching. + return false if @force_no_page @server_caps ||= search_root_dse @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) end diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 929f55ec..47ab03f4 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -21,17 +21,17 @@ class << self # attribute_value = "" def generate(type, str) - case type - when :md5 - attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! - when :sha - attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! - when :ssha - salt = SecureRandom.random_bytes(16) - attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! - else - raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" - end + case type + when :md5 + attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! + when :sha + attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! + when :ssha + salt = SecureRandom.random_bytes(16) + attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! + else + raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" + end return attribute_value end end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 3f9e5fb1..501df851 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -3,268 +3,262 @@ # :stopdoc: module Net - class SNMP - VERSION = Net::LDAP::VERSION + class SNMP + VERSION = Net::LDAP::VERSION + AsnSyntax = Net::BER.compile_syntax({ + :application => { + :primitive => { + 1 => :integer, # Counter32, (RFC2578 sec 2) + 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2) + 3 => :integer # TimeTicks32, (RFC2578 sec 2) + }, + :constructed => {} + }, + :context_specific => { + :primitive => {}, + :constructed => { + 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2) + 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3) + 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4) + } + } + }) - AsnSyntax = Net::BER.compile_syntax({ - :application => { - :primitive => { - 1 => :integer, # Counter32, (RFC2578 sec 2) - 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2) - 3 => :integer # TimeTicks32, (RFC2578 sec 2) - }, - :constructed => { - } - }, - :context_specific => { - :primitive => { - }, - :constructed => { - 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2) - 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3) - 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4) - } - } - }) - - # SNMP 32-bit counter. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer - # with a range from 0 to 2^^32 - 1. - class Counter32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(1) - end - end - - # SNMP 32-bit gauge. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer. - # This is also indistinguishable from Unsigned32. (Need to alias them.) - class Gauge32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(2) - end - end - - # SNMP 32-bit timer-ticks. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer. - class TimeTicks32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(3) - end - end + # SNMP 32-bit counter. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer + # with a range from 0 to 2^^32 - 1. + class Counter32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(1) + end end - class SnmpPdu - class Error < StandardError; end - - PduTypes = [ - :get_request, - :get_next_request, - :get_response, - :set_request, - :trap - ] - ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1 - 0 => "noError", - 1 => "tooBig", - 2 => "noSuchName", - 3 => "badValue", - 4 => "readOnly", - 5 => "genErr" - } + # SNMP 32-bit gauge. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer. + # This is also indistinguishable from Unsigned32. (Need to alias them.) + class Gauge32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(2) + end + end - class << self - def parse ber_object - n = new - n.send :parse, ber_object - n - end - end + # SNMP 32-bit timer-ticks. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer. + class TimeTicks32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(3) + end + end + end - attr_reader :version, :community, :pdu_type, :variables, :error_status - attr_accessor :request_id, :error_index + class SnmpPdu + class Error < StandardError; end + PduTypes = [ + :get_request, + :get_next_request, + :get_response, + :set_request, + :trap + ] + ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1 + 0 => "noError", + 1 => "tooBig", + 2 => "noSuchName", + 3 => "badValue", + 4 => "readOnly", + 5 => "genErr" + } + class << self + def parse ber_object + n = new + n.send :parse, ber_object + n + end + end - def initialize args={} - @version = args[:version] || 0 - @community = args[:community] || "public" - @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value. - @error_status = args[:error_status] || 0 - @error_index = args[:error_index] || 0 - @variables = args[:variables] || [] - end + attr_reader :version, :community, :pdu_type, :variables, :error_status + attr_accessor :request_id, :error_index - #-- - def parse ber_object - begin - parse_ber_object ber_object - rescue Error - # Pass through any SnmpPdu::Error instances - raise $! - rescue - # Wrap any basic parsing error so it becomes a PDU-format error - raise Error.new( "snmp-pdu format error" ) - end - end - private :parse + def initialize args={} + @version = args[:version] || 0 + @community = args[:community] || "public" + @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value. + @error_status = args[:error_status] || 0 + @error_index = args[:error_index] || 0 + @variables = args[:variables] || [] + end - def parse_ber_object ber_object - send :version=, ber_object[0].to_i - send :community=, ber_object[1].to_s + #-- + def parse ber_object + begin + parse_ber_object ber_object + rescue Error + # Pass through any SnmpPdu::Error instances + raise $! + rescue + # Wrap any basic parsing error so it becomes a PDU-format error + raise Error.new( "snmp-pdu format error" ) + end + end + private :parse - data = ber_object[2] - case (app_tag = data.ber_identifier & 31) - when 0 - send :pdu_type=, :get_request - parse_get_request data - when 1 - send :pdu_type=, :get_next_request - # This PDU is identical to get-request except for the type. - parse_get_request data - when 2 - send :pdu_type=, :get_response - # This PDU is identical to get-request except for the type, - # the error_status and error_index values are meaningful, - # and the fact that the variable bindings will be non-null. - parse_get_response data - else - raise Error.new( "unknown snmp-pdu type: #{app_tag}" ) - end - end - private :parse_ber_object + def parse_ber_object ber_object + send :version=, ber_object[0].to_i + send :community=, ber_object[1].to_s - #-- - # Defined in RFC1157, pgh 4.1.2. - def parse_get_request data - send :request_id=, data[0].to_i - # data[1] is error_status, always zero. - # data[2] is error_index, always zero. - send :error_status=, 0 - send :error_index=, 0 - data[3].each {|n,v| - # A variable-binding, of which there may be several, - # consists of an OID and a BER null. - # We're ignoring the null, we might want to verify it instead. - unless v.is_a?(Net::BER::BerIdentifiedNull) - raise Error.new(" invalid variable-binding in get-request" ) - end - add_variable_binding n, nil - } - end - private :parse_get_request + data = ber_object[2] + case (app_tag = data.ber_identifier & 31) + when 0 + send :pdu_type=, :get_request + parse_get_request data + when 1 + send :pdu_type=, :get_next_request + # This PDU is identical to get-request except for the type. + parse_get_request data + when 2 + send :pdu_type=, :get_response + # This PDU is identical to get-request except for the type, + # the error_status and error_index values are meaningful, + # and the fact that the variable bindings will be non-null. + parse_get_response data + else + raise Error.new( "unknown snmp-pdu type: #{app_tag}" ) + end + end + private :parse_ber_object - #-- - # Defined in RFC1157, pgh 4.1.4 - def parse_get_response data - send :request_id=, data[0].to_i - send :error_status=, data[1].to_i - send :error_index=, data[2].to_i - data[3].each {|n,v| - # A variable-binding, of which there may be several, - # consists of an OID and a BER null. - # We're ignoring the null, we might want to verify it instead. - add_variable_binding n, v - } - end - private :parse_get_response + #-- + # Defined in RFC1157, pgh 4.1.2. + def parse_get_request data + send :request_id=, data[0].to_i + # data[1] is error_status, always zero. + # data[2] is error_index, always zero. + send :error_status=, 0 + send :error_index=, 0 + data[3].each do |n,v| + # A variable-binding, of which there may be several, + # consists of an OID and a BER null. + # We're ignoring the null, we might want to verify it instead. + unless v.is_a?(Net::BER::BerIdentifiedNull) + raise Error.new(" invalid variable-binding in get-request" ) + end + add_variable_binding n, nil + end + end + private :parse_get_request + #-- + # Defined in RFC1157, pgh 4.1.4 + def parse_get_response data + send :request_id=, data[0].to_i + send :error_status=, data[1].to_i + send :error_index=, data[2].to_i + data[3].each do |n,v| + # A variable-binding, of which there may be several, + # consists of an OID and a BER null. + # We're ignoring the null, we might want to verify it instead. + add_variable_binding n, v + end + end + private :parse_get_response - def version= ver - unless [0,2].include?(ver) - raise Error.new("unknown snmp-version: #{ver}") - end - @version = ver - end - def pdu_type= t - unless PduTypes.include?(t) - raise Error.new("unknown pdu-type: #{t}") - end - @pdu_type = t - end + def version= ver + unless [0,2].include?(ver) + raise Error.new("unknown snmp-version: #{ver}") + end + @version = ver + end - def error_status= es - unless ErrorStatusCodes.has_key?(es) - raise Error.new("unknown error-status: #{es}") - end - @error_status = es - end + def pdu_type= t + unless PduTypes.include?(t) + raise Error.new("unknown pdu-type: #{t}") + end + @pdu_type = t + end - def community= c - @community = c.to_s - end + def error_status= es + unless ErrorStatusCodes.has_key?(es) + raise Error.new("unknown error-status: #{es}") + end + @error_status = es + end - #-- - # Syntactic sugar - def add_variable_binding name, value=nil - @variables ||= [] - @variables << [name, value] - end + def community= c + @community = c.to_s + end - def to_ber_string - [ - version.to_ber, - community.to_ber, - pdu_to_ber_string - ].to_ber_sequence - end + #-- + # Syntactic sugar + def add_variable_binding name, value=nil + @variables ||= [] + @variables << [name, value] + end - #-- - # Helper method that returns a PDU payload in BER form, - # depending on the PDU type. - def pdu_to_ber_string - case pdu_type - when :get_request - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(0) - when :get_next_request - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(1) - when :get_response - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, v.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(2) - else - raise Error.new( "unknown pdu-type: #{pdu_type}" ) - end - end - private :pdu_to_ber_string + def to_ber_string + [ + version.to_ber, + community.to_ber, + pdu_to_ber_string, + ].to_ber_sequence + end + #-- + # Helper method that returns a PDU payload in BER form, + # depending on the PDU type. + def pdu_to_ber_string + case pdu_type + when :get_request + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(0) + when :get_next_request + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(1) + when :get_response + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, v.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(2) + else + raise Error.new( "unknown pdu-type: #{pdu_type}" ) + end end + private :pdu_to_ber_string + end end # :startdoc: diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index 68242c43..b59578d2 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -4,23 +4,23 @@ require 'net/ldap' describe "BER encoding of" do - + RSpec::Matchers.define :properly_encode_and_decode do match do |given| given.to_ber.read_ber.should == given end end - + context "arrays" do it "should properly encode/decode []" do [].should properly_encode_and_decode - end + end it "should properly encode/decode [1,2,3]" do ary = [1,2,3] encoded_ary = ary.map { |el| el.to_ber }.to_ber - + encoded_ary.read_ber.should == ary - end + end end context "booleans" do it "should encode true" do @@ -62,14 +62,12 @@ it "should correctly handle powers of two" do 100.times do |p| n = 2 << p - n.should properly_encode_and_decode end end it "should correctly handle powers of ten" do 100.times do |p| n = 5 * 10**p - n.should properly_encode_and_decode end end @@ -84,11 +82,11 @@ it "should properly encode strings encodable as UTF-8" do "teststring".encode("US-ASCII").to_ber.should == "\x04\nteststring" end - it "should properly encode binary data strings using to_ber_bin" do - # This is used for searching for GUIDs in Active Directory - ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == - raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") - end + it "should properly encode binary data strings using to_ber_bin" do + # This is used for searching for GUIDs in Active Directory + ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should == + raw_string("\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16") + end it "should not fail on strings that can not be converted to UTF-8" do expect { "\x81".to_ber }.not_to raise_error end diff --git a/test/test_entry.rb b/test/test_entry.rb index 73898d67..c89c81af 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -54,6 +54,6 @@ class TestEntry < Test::Unit::TestCase assert_equal ['Jensen'], @entry['Sn'] assert_equal ['Jensen'], @entry['SN'] end - end + end end =end diff --git a/test/test_filter.rb b/test/test_filter.rb index 03436e03..bec772de 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -28,7 +28,7 @@ def test_convenience_filters assert_equal("(uid=\\2A)", Filter.equals("uid", "*").to_s) assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s) assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s) - assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) + assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) end def test_c2 diff --git a/test/test_password.rb b/test/test_password.rb index abc8c22b..d7b4e592 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -3,15 +3,8 @@ require 'common' class TestPassword < Test::Unit::TestCase - def test_psw - assert_equal( - "{MD5}xq8jwrcfibi0sZdZYNkSng==", - Net::LDAP::Password.generate( :md5, "cashflow" )) - - assert_equal( - "{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", - Net::LDAP::Password.generate( :sha, "cashflow" )) + assert_equal("{MD5}xq8jwrcfibi0sZdZYNkSng==", Net::LDAP::Password.generate( :md5, "cashflow" )) + assert_equal("{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", Net::LDAP::Password.generate( :sha, "cashflow" )) end - end From f4c1b94f0f751a63ebebd2a189b0c183080defa1 Mon Sep 17 00:00:00 2001 From: Nolan Date: Tue, 14 Oct 2014 09:55:59 -0700 Subject: [PATCH 173/435] fix trailing whitespaces --- lib/net/ber/core_ext.rb | 10 +++++----- lib/net/ldap.rb | 2 +- lib/net/ldap/entry.rb | 2 +- lib/net/ldap/filter.rb | 14 +++++++------- spec/integration/ssl_ber_spec.rb | 18 ++++++++--------- spec/unit/ber/ber_spec.rb | 8 ++++---- spec/unit/ber/core_ext/string_spec.rb | 14 +++++++------- spec/unit/ldap/dn_spec.rb | 4 ++-- spec/unit/ldap/entry_spec.rb | 16 +++++++-------- spec/unit/ldap/filter_spec.rb | 28 +++++++++++++-------------- test/test_filter.rb | 2 +- test/test_rename.rb | 2 +- 12 files changed, 60 insertions(+), 60 deletions(-) diff --git a/lib/net/ber/core_ext.rb b/lib/net/ber/core_ext.rb index b176df7f..f46acb89 100644 --- a/lib/net/ber/core_ext.rb +++ b/lib/net/ber/core_ext.rb @@ -28,35 +28,35 @@ class String require 'net/ber/core_ext/array' # :stopdoc: -class Array +class Array include Net::BER::Extensions::Array end # :startdoc: require 'net/ber/core_ext/bignum' # :stopdoc: -class Bignum +class Bignum include Net::BER::Extensions::Bignum end # :startdoc: require 'net/ber/core_ext/fixnum' # :stopdoc: -class Fixnum +class Fixnum include Net::BER::Extensions::Fixnum end # :startdoc: require 'net/ber/core_ext/true_class' # :stopdoc: -class TrueClass +class TrueClass include Net::BER::Extensions::TrueClass end # :startdoc: require 'net/ber/core_ext/false_class' # :stopdoc: -class FalseClass +class FalseClass include Net::BER::Extensions::FalseClass end # :startdoc: diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index d4d919c8..4faaad7b 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -486,7 +486,7 @@ def authenticate(username, password) # standard port for simple-TLS encrypted connections is 636. Be sure you # are using the correct port. # - # The :start_tls like the :simple_tls encryption method also encrypts all + # The :start_tls like the :simple_tls encryption method also encrypts all # communcations with the LDAP server. With the exception that it operates # over the standard TCP port. def encryption(args) diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index f27380e3..06943a93 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -115,7 +115,7 @@ def [](name) ## # Read the first value for the provided attribute. The attribute name - # is canonicalized prior to reading. Returns nil if the attribute does + # is canonicalized prior to reading. Returns nil if the attribute does # not exist. def first(name) self[name].first diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 9df345b8..5d91f9f6 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -242,7 +242,7 @@ def present?(attribute) # http://tools.ietf.org/html/rfc4515 lists these exceptions from UTF1 # charset for filters. All of the following must be escaped in any normal - # string using a single backslash ('\') as escape. + # string using a single backslash ('\') as escape. # ESCAPES = { "\0" => '00', # NUL = %x00 ; null character @@ -251,10 +251,10 @@ def present?(attribute) ')' => '29', # RPARENS = %x29 ; right parenthesis (")") '\\' => '5C', # ESC = %x5C ; esc (or backslash) ("\") } - # Compiled character class regexp using the keys from the above hash. + # Compiled character class regexp using the keys from the above hash. ESCAPE_RE = Regexp.new( - "[" + - ESCAPES.keys.map { |e| Regexp.escape(e) }.join + + "[" + + ESCAPES.keys.map { |e| Regexp.escape(e) }.join + "]") ## @@ -310,8 +310,8 @@ def parse_ber(ber) present?(ber.to_s) when 0xa9 # context-specific constructed 9, "extensible comparison" raise Net::LDAP::LdapError, "Invalid extensible search filter, should be at least two elements" if ber.size<2 - - # Reassembles the extensible filter parts + + # Reassembles the extensible filter parts # (["sn", "2.4.6.8.10", "Barbara Jones", '1']) type = value = dn = rule = nil ber.each do |element| @@ -327,7 +327,7 @@ def parse_ber(ber) attribute << type if type attribute << ":#{dn}" if dn attribute << ":#{rule}" if rule - + ex(attribute, value) else raise Net::LDAP::LdapError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter." diff --git a/spec/integration/ssl_ber_spec.rb b/spec/integration/ssl_ber_spec.rb index ae8900e3..0bdec964 100644 --- a/spec/integration/ssl_ber_spec.rb +++ b/spec/integration/ssl_ber_spec.rb @@ -4,7 +4,7 @@ require 'timeout' describe "BER serialisation (SSL)" do - # Transmits str to #to and reads it back from #from. + # Transmits str to #to and reads it back from #from. # def transmit(str) Timeout::timeout(1) do @@ -14,26 +14,26 @@ def transmit(str) from.read end end - + attr_reader :to, :from before(:each) do @from, @to = IO.pipe - + # The production code operates on sockets, which do need #connect called - # on them to work. Pipes are more robust for this test, so we'll skip - # the #connect call since it fails. + # on them to work. Pipes are more robust for this test, so we'll skip + # the #connect call since it fails. flexmock(OpenSSL::SSL::SSLSocket). new_instances.should_receive(:connect => nil) - + @to = Net::LDAP::Connection.wrap_with_ssl(to) @from = Net::LDAP::Connection.wrap_with_ssl(from) end - + it "should transmit strings" do transmit('foo').should == 'foo' - end + end it "should correctly transmit numbers" do to.write 1234.to_ber from.read_ber.should == 1234 - end + end end \ No newline at end of file diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb index b59578d2..b50c8ab1 100644 --- a/spec/unit/ber/ber_spec.rb +++ b/spec/unit/ber/ber_spec.rb @@ -5,7 +5,7 @@ describe "BER encoding of" do - RSpec::Matchers.define :properly_encode_and_decode do + RSpec::Matchers.define :properly_encode_and_decode do match do |given| given.to_ber.read_ber.should == given end @@ -64,13 +64,13 @@ n = 2 << p n.should properly_encode_and_decode end - end + end it "should correctly handle powers of ten" do 100.times do |p| n = 5 * 10**p n.should properly_encode_and_decode end - end + end end end if "Ruby 1.9".respond_to?(:encoding) @@ -106,7 +106,7 @@ "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus". read_ber(Net::LDAP::AsnSyntax).should == [1, [3, "Administrator", "ad_is_bogus"]] - end + end end end diff --git a/spec/unit/ber/core_ext/string_spec.rb b/spec/unit/ber/core_ext/string_spec.rb index ef2c4981..edcd4403 100644 --- a/spec/unit/ber/core_ext/string_spec.rb +++ b/spec/unit/ber/core_ext/string_spec.rb @@ -9,10 +9,10 @@ @str = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED") @result = str.read_ber!(Net::LDAP::AsnSyntax) end - + it "should correctly parse the ber message" do result.should == [1, [3, "Administrator", "ad_is_bogus"]] - end + end it "should leave unconsumed part of message in place" do str.should == " UNCONSUMED" end @@ -21,9 +21,9 @@ attr_reader :initial_value before(:each) do stub_exception_class = Class.new(StandardError) - + @initial_value = raw_string("0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus") - @str = initial_value.dup + @str = initial_value.dup # Defines a string io = StringIO.new(initial_value) @@ -32,16 +32,16 @@ raise stub_exception_class end flexmock(StringIO).should_receive(:new).and_return(io) - + begin - str.read_ber!(Net::LDAP::AsnSyntax) + str.read_ber!(Net::LDAP::AsnSyntax) rescue stub_exception_class # EMPTY ON PURPOSE else raise "The stub code should raise an exception!" end end - + it "should not modify string" do str.should == initial_value end diff --git a/spec/unit/ldap/dn_spec.rb b/spec/unit/ldap/dn_spec.rb index 8d1b5852..7ada3b40 100644 --- a/spec/unit/ldap/dn_spec.rb +++ b/spec/unit/ldap/dn_spec.rb @@ -11,7 +11,7 @@ it "should construct a Net::LDAP::DN" do dn.should be_an_instance_of(Net::LDAP::DN) - end + end it "should escape all the required characters" do dn.to_s.should == 'cn=\\,\\+\\"\\\\\\<\\>\\;,ou=company' @@ -75,6 +75,6 @@ describe "<- .escape(str)" do it "should escape ,, +, \", \\, <, >, and ;" do Net::LDAP::DN.escape(',+"\\<>;').should == '\\,\\+\\"\\\\\\<\\>\\;' - end + end end end diff --git a/spec/unit/ldap/entry_spec.rb b/spec/unit/ldap/entry_spec.rb index e0270cbd..2e52747b 100644 --- a/spec/unit/ldap/entry_spec.rb +++ b/spec/unit/ldap/entry_spec.rb @@ -14,12 +14,12 @@ describe "entry access" do it "should always respond to #dn" do entry.should respond_to(:dn) - end - + end + context "<- #foo" do it "should respond_to?" do entry.should respond_to(:foo) - end + end it "should return 'foo'" do entry.foo.should == ['foo'] end @@ -27,25 +27,25 @@ context "<- #Foo" do it "should respond_to?" do entry.should respond_to(:Foo) - end + end it "should return 'foo'" do entry.foo.should == ['foo'] - end + end end context "<- #foo=" do it "should respond_to?" do entry.should respond_to(:foo=) - end + end it "should set 'foo'" do entry.foo= 'bar' entry.foo.should == ['bar'] - end + end end context "<- #fOo=" do it "should return 'foo'" do entry.fOo= 'bar' entry.fOo.should == ['bar'] - end + end end end end \ No newline at end of file diff --git a/spec/unit/ldap/filter_spec.rb b/spec/unit/ldap/filter_spec.rb index 06fd3b80..0ffe5f5b 100644 --- a/spec/unit/ldap/filter_spec.rb +++ b/spec/unit/ldap/filter_spec.rb @@ -9,21 +9,21 @@ end it "should convert to 'foo:=bar'" do filter.to_s.should == '(foo:=bar)' - end + end it "should survive roundtrip via to_s/from_rfc2254" do Net::LDAP::Filter.from_rfc2254(filter.to_s).should == filter - end + end it "should survive roundtrip conversion to/from ber" do ber = filter.to_ber Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should == filter - end + end end context "various legal inputs" do [ - '(o:dn:=Ace Industry)', - '(:dn:2.4.8.10:=Dino)', - '(cn:dn:1.2.3.4.5:=John Smith)', + '(o:dn:=Ace Industry)', + '(:dn:2.4.8.10:=Dino)', + '(cn:dn:1.2.3.4.5:=John Smith)', '(sn:dn:2.4.6.8.10:=Barbara Jones)', '(&(sn:dn:2.4.6.8.10:=Barbara Jones))' ].each do |filter_str| @@ -35,12 +35,12 @@ it "should decode into a Net::LDAP::Filter" do filter.should be_an_instance_of(Net::LDAP::Filter) - end + end it "should survive roundtrip conversion to/from ber" do ber = filter.to_ber Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should == filter - end + end end end end @@ -48,7 +48,7 @@ describe "<- .construct" do it "should accept apostrophes in filters (regression)" do Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)" - end + end end describe "convenience filter constructors" do @@ -58,28 +58,28 @@ def eq(attribute, value) describe "<- .equals(attr, val)" do it "should delegate to .eq with escaping" do described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo') - end + end end describe "<- .begins(attr, val)" do it "should delegate to .eq with escaping" do described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*') - end + end end describe "<- .ends(attr, val)" do it "should delegate to .eq with escaping" do described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo') - end + end end describe "<- .contains(attr, val)" do it "should delegate to .eq with escaping" do described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*') - end + end end end describe "<- .escape(str)" do it "should escape nul, *, (, ) and \\" do Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C" - end + end end context 'with a well-known BER string' do diff --git a/test/test_filter.rb b/test/test_filter.rb index bec772de..7e1e13d8 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -28,7 +28,7 @@ def test_convenience_filters assert_equal("(uid=\\2A)", Filter.equals("uid", "*").to_s) assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s) assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s) - assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) + assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s) end def test_c2 diff --git a/test/test_rename.rb b/test/test_rename.rb index db82340a..1d2e7e30 100644 --- a/test/test_rename.rb +++ b/test/test_rename.rb @@ -1,7 +1,7 @@ require 'common' # Commented out since it assumes you have a live LDAP server somewhere. This -# will be migrated to the integration specs, as soon as they are ready. +# will be migrated to the integration specs, as soon as they are ready. =begin class TestRename < Test::Unit::TestCase HOST= '10.10.10.71' From 26ebfff2ef5f73d6885676a5aa5e18c6167a6532 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 14 Oct 2014 18:07:06 -0700 Subject: [PATCH 174/435] Override Test::Unit::TestCase#run for disabled integration tests --- test/test_integration.rb | 62 +++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/test/test_integration.rb b/test/test_integration.rb index 58e5468f..294c1e1d 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -1,38 +1,42 @@ require_relative 'test_helper' -if !INTEGRATION - puts "Skipping integration tests..." -else - class TestLDAPIntegration < Test::Unit::TestCase - def setup - @service = MockInstrumentationService.new - @ldap = Net::LDAP.new \ - host: 'localhost', - port: 389, - admin_user: 'uid=admin,dc=rubyldap,dc=com', - admin_password: 'passworD1', - search_domains: %w(dc=rubyldap,dc=com), - uid: 'uid', - instrumentation_service: @service - end +class TestLDAPIntegration < Test::Unit::TestCase - def test_bind_success - assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect + # If integration tests aren't enabled, noop these tests. + if !INTEGRATION + def run(*) + self end + end - def test_bind_anonymous_fail - refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect + def setup + @service = MockInstrumentationService.new + @ldap = Net::LDAP.new \ + host: 'localhost', + port: 389, + admin_user: 'uid=admin,dc=rubyldap,dc=com', + admin_password: 'passworD1', + search_domains: %w(dc=rubyldap,dc=com), + uid: 'uid', + instrumentation_service: @service + end - result = @ldap.get_operation_result - assert_equal 53, result.code - assert_equal "Unwilling to perform", result.message - assert_equal "unauthenticated bind (DN with no password) disallowed", - result.error_message - assert_equal "", result.matched_dn - end + def test_bind_success + assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect + end - def test_bind_fail - refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect - end + def test_bind_anonymous_fail + refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect + + result = @ldap.get_operation_result + assert_equal 53, result.code + assert_equal "Unwilling to perform", result.message + assert_equal "unauthenticated bind (DN with no password) disallowed", + result.error_message + assert_equal "", result.matched_dn + end + + def test_bind_fail + refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect end end From 54dcd12fb7621e20369de6843c1c6fe5f4c10e1a Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 14 Oct 2014 18:20:49 -0700 Subject: [PATCH 175/435] Move bind integration test under test/integration/ Use an abstract integration test case. --- .../test_bind.rb} | 22 +------------------ test/test_helper.rb | 21 ++++++++++++++++++ 2 files changed, 22 insertions(+), 21 deletions(-) rename test/{test_integration.rb => integration/test_bind.rb} (61%) diff --git a/test/test_integration.rb b/test/integration/test_bind.rb similarity index 61% rename from test/test_integration.rb rename to test/integration/test_bind.rb index 294c1e1d..b3692974 100644 --- a/test/test_integration.rb +++ b/test/integration/test_bind.rb @@ -1,26 +1,6 @@ require_relative 'test_helper' -class TestLDAPIntegration < Test::Unit::TestCase - - # If integration tests aren't enabled, noop these tests. - if !INTEGRATION - def run(*) - self - end - end - - def setup - @service = MockInstrumentationService.new - @ldap = Net::LDAP.new \ - host: 'localhost', - port: 389, - admin_user: 'uid=admin,dc=rubyldap,dc=com', - admin_password: 'passworD1', - search_domains: %w(dc=rubyldap,dc=com), - uid: 'uid', - instrumentation_service: @service - end - +class TestBindIntegration < LDAPIntegrationTestCase def test_bind_success assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end diff --git a/test/test_helper.rb b/test/test_helper.rb index 70d4b70d..adea8078 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -31,3 +31,24 @@ def subscribe(event) @events[event] end end + +class LDAPIntegrationTestCase < Test::Unit::TestCase + # If integration tests aren't enabled, noop these tests. + if !INTEGRATION + def run(*) + self + end + end + + def setup + @service = MockInstrumentationService.new + @ldap = Net::LDAP.new \ + host: 'localhost', + port: 389, + admin_user: 'uid=admin,dc=rubyldap,dc=com', + admin_password: 'passworD1', + search_domains: %w(dc=rubyldap,dc=com), + uid: 'uid', + instrumentation_service: @service + end +end From 03e0ec6753230b5bbe45f0446d68dae8dd3abad5 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 14 Oct 2014 18:22:24 -0700 Subject: [PATCH 176/435] Relative path has changed --- test/integration/test_bind.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index b3692974..5ec1b63f 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -1,4 +1,4 @@ -require_relative 'test_helper' +require_relative '../test_helper' class TestBindIntegration < LDAPIntegrationTestCase def test_bind_success From a589c8b42565d58f412421abcd0ae003fcb17eb3 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 14 Oct 2014 18:28:23 -0700 Subject: [PATCH 177/435] Add basic search integration tests --- test/integration/test_search.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/integration/test_search.rb diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb new file mode 100644 index 00000000..6c266488 --- /dev/null +++ b/test/integration/test_search.rb @@ -0,0 +1,27 @@ +require_relative '../test_helper' + +class TestSearchIntegration < LDAPIntegrationTestCase + def test_search + entries = [] + + result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com") do |entry| + assert_kind_of Net::LDAP::Entry, entry + entries << entry + end + + refute entries.empty? + assert_equal entries, result + end + + def test_search_without_result + entries = [] + + result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com") do |entry| + assert_kind_of Net::LDAP::Entry, entry + entries << entry + end + + assert result + refute_equal entries, result + end +end From 50b651bd2127265f0a6eac02e8e95934c0d2e2de Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 14 Oct 2014 23:28:49 -0700 Subject: [PATCH 178/435] Testing return_result: false --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 6c266488..77eea8c4 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -16,7 +16,7 @@ def test_search def test_search_without_result entries = [] - result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com") do |entry| + result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", return_result: false) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end From 180e615b70e377f62c24bb9e0b9f4d487762e521 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 12:22:24 -0700 Subject: [PATCH 179/435] Allow integration host override --- test/test_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index adea8078..f208977d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -43,7 +43,7 @@ def run(*) def setup @service = MockInstrumentationService.new @ldap = Net::LDAP.new \ - host: 'localhost', + host: ENV.fetch('INTEGRATION_HOST', 'localhost'), port: 389, admin_user: 'uid=admin,dc=rubyldap,dc=com', admin_password: 'passworD1', From 15a99a781db25594f5a7650739bc326e5d1d60ca Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 12:22:46 -0700 Subject: [PATCH 180/435] Add Vagrant VM for local integration testing --- test/support/vm/openldap/.gitignore | 1 + test/support/vm/openldap/README.md | 30 +++++++++++++++++++++++++ test/support/vm/openldap/Vagrantfile | 33 ++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 test/support/vm/openldap/.gitignore create mode 100644 test/support/vm/openldap/README.md create mode 100644 test/support/vm/openldap/Vagrantfile diff --git a/test/support/vm/openldap/.gitignore b/test/support/vm/openldap/.gitignore new file mode 100644 index 00000000..dace7081 --- /dev/null +++ b/test/support/vm/openldap/.gitignore @@ -0,0 +1 @@ +/.vagrant diff --git a/test/support/vm/openldap/README.md b/test/support/vm/openldap/README.md new file mode 100644 index 00000000..b4c3bd33 --- /dev/null +++ b/test/support/vm/openldap/README.md @@ -0,0 +1,30 @@ +# Local OpenLDAP Integration Testing + +Set up a VM to run integration tests against OpenLDAP locally. + +To run integration tests locally: + +``` bash +# start VM (from the correct directory) +$ cd test/support/vm/openldap/ +$ vagrant up + +# get the IP address of the VM +$ ip=$(vagrant ssh -- "ifconfig eth1 | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n1") + +# change back to root project directory +$ cd ../../../.. + +# run all tests, including integration tests +$ time INTEGRATION=openldap INTEGRATION_HOST=$ip bundle exec rake + +# run a specific integration test file +$ time INTEGRATION=openldap INTEGRATION_HOST=$ip bundle exec ruby test/integration/test_search.rb + +# run integration tests by default +$ export INTEGRATION=openldap +$ export INTEGRATION_HOST=$ip + +# now run tests without having to set ENV variables +$ time bundle exec rake +``` diff --git a/test/support/vm/openldap/Vagrantfile b/test/support/vm/openldap/Vagrantfile new file mode 100644 index 00000000..0aaa4feb --- /dev/null +++ b/test/support/vm/openldap/Vagrantfile @@ -0,0 +1,33 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.hostname = "freeipa.ghe.local" + + config.vm.box = "hashicorp/precise64" + + config.vm.network "private_network", type: :dhcp + + config.ssh.forward_agent = true + + config.vm.provision "shell", inline: "apt-get update; exec env /vagrant_data/script/install-openldap" + + config.vm.synced_folder "../../../..", "/vagrant_data" + + config.vm.provider "vmware_fusion" do |vb, override| + override.vm.box = "hashicorp/precise64" + vb.memory = 4596 + vb.vmx["displayname"] = "integration tests vm" + vb.vmx["numvcpus"] = "2" + end + + config.vm.provider "virtualbox" do |vb, override| + vb.memory = 4096 + vb.customize ["modifyvm", :id, "--nicpromisc2", "allow-all"] + vb.customize ["modifyvm", :id, "--chipset", "ich9"] + vb.customize ["modifyvm", :id, "--vram", "16"] + end +end From 85ec2d2d3b33ded346007835a1ae51fdc473ab7c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 12:45:08 -0700 Subject: [PATCH 181/435] No need to run CI without integration tests --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20946629..5a4b33cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ rvm: # - rbx-2 env: - - INTEGRATION=skip - INTEGRATION=openldap install: From 6bd5369d6ec273058460eb907ab8ebf74a5ce797 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 12:58:29 -0700 Subject: [PATCH 182/435] Enable Rubinius 2.x builds, make Rubinius optional --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4dd7b6dc..df9a77ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,13 @@ rvm: - 1.9.3 - 2.0.0 - 2.1.2 + # optional - jruby-19mode - rbx-19mode - # - rbx-2 + - rbx-2 matrix: allow_failures: - rvm: jruby-19mode + - rvm: rbx-19mode + - rvm: rbx-2 script: bundle exec rake From a90e3fcccb34972b9baead2008d38fca445f6376 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 13:09:54 -0700 Subject: [PATCH 183/435] Formatting, fast finish --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index df9a77ba..0e3b0cf7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,12 @@ rvm: - jruby-19mode - rbx-19mode - rbx-2 + matrix: allow_failures: - rvm: jruby-19mode - rvm: rbx-19mode - rvm: rbx-2 + fast_finish: true + script: bundle exec rake From 77862a2f2db70a2e89620329ee7aa825e54a0c4d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 14:10:08 -0700 Subject: [PATCH 184/435] Link to Vagrant, clarify installing vagrant binary --- test/support/vm/openldap/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/support/vm/openldap/README.md b/test/support/vm/openldap/README.md index b4c3bd33..a2769567 100644 --- a/test/support/vm/openldap/README.md +++ b/test/support/vm/openldap/README.md @@ -1,6 +1,6 @@ # Local OpenLDAP Integration Testing -Set up a VM to run integration tests against OpenLDAP locally. +Set up a [Vagrant](http://www.vagrantup.com/) VM to run integration tests against OpenLDAP locally. To run integration tests locally: @@ -28,3 +28,5 @@ $ export INTEGRATION_HOST=$ip # now run tests without having to set ENV variables $ time bundle exec rake ``` + +You may need to `gem install vagrant` first in order to provision the VM. From 2fb8067c9164ade56dcc8f0a27d68a5094d20d58 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 16:30:02 -0700 Subject: [PATCH 185/435] Move Net::LDAP::PDU parsing to Net::LDAP::Connection#read Adds instrumenting of the parsed PDU. --- lib/net/ldap/connection.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 69baa57f..ac4be369 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -119,13 +119,25 @@ def close # # - syntax: the BER syntax to use to parse the read data with # - # Returns basic BER objects. + # Returns parsed Net::LDAP::PDU object. def read(syntax = Net::LDAP::AsnSyntax) - instrument "read.net_ldap_connection", :syntax => syntax do |payload| - @conn.read_ber(syntax) do |id, content_length| - payload[:object_type_id] = id - payload[:content_length] = content_length + ber_object = + instrument "read.net_ldap_connection", :syntax => syntax do |payload| + @conn.read_ber(syntax) do |id, content_length| + payload[:object_type_id] = id + payload[:content_length] = content_length + end end + + return unless ber_object + + instrument "parse_pdu.net_ldap_connection" do |payload| + pdu = payload[:pdu] = Net::LDAP::PDU.new(ber_object) + + payload[:message_id] = pdu.message_id + payload[:app_tag] = pdu.app_tag + + pdu end end private :read From 1068fa9165365a5e1738c9ebb2b62fc20f081371 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 16:33:18 -0700 Subject: [PATCH 186/435] Remove Net::LDAP::PDU parsing calls replaced by new read behavior --- lib/net/ldap/connection.rb | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index ac4be369..a10b7774 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -91,9 +91,7 @@ def setup_encryption(args) request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) request_pkt = [msgid, request].to_ber_sequence write request_pkt - be = read - raise Net::LDAP::LdapError, "no start_tls result" if be.nil? - pdu = Net::LDAP::PDU.new(be) + pdu = read raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn) @@ -194,7 +192,7 @@ def bind_simple(auth) request_pkt = [msgid, request].to_ber_sequence write request_pkt - (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (pdu = read) or raise Net::LDAP::LdapError, "no bind result" pdu end @@ -233,7 +231,7 @@ def bind_sasl(auth) request_pkt = [msgid, request].to_ber_sequence write request_pkt - (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result" + (pdu = read) or raise Net::LDAP::LdapError, "no bind result" return pdu unless pdu.result_code == 14 # saslBindInProgress raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) @@ -411,7 +409,7 @@ def search(args = {}) result_pdu = nil controls = [] - while (be = read) && (pdu = Net::LDAP::PDU.new(be)) + while (pdu = read) case pdu.app_tag when Net::LDAP::PDU::SearchReturnedData n_results += 1 @@ -517,7 +515,7 @@ def modify(args) pkt = [ next_msgid.to_ber, request ].to_ber_sequence write pkt - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + (pdu = read) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end @@ -540,8 +538,7 @@ def add(args) pkt = [next_msgid.to_ber, request].to_ber_sequence write pkt - (be = read) && - (pdu = Net::LDAP::PDU.new(be)) && + (pdu = read) && (pdu.app_tag == Net::LDAP::PDU::AddResponse) or raise Net::LDAP::LdapError, "response missing or invalid" @@ -563,8 +560,8 @@ def rename(args) pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence write pkt - (be = read) && - (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or + (pdu = read) && + (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or raise Net::LDAP::LdapError.new( "response missing or invalid" ) pdu @@ -580,7 +577,7 @@ def delete(args) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence write pkt - (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + (pdu = read) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" pdu end From e0912eadc9245c28213ec2976058ae21c663218d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 17:25:19 -0700 Subject: [PATCH 187/435] Add unit test for parse_pdu.net_ldap_connection event --- test/test_ldap_connection.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index d62c5992..d16b48a5 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -121,6 +121,28 @@ def test_read_net_ldap_connection_event assert_equal read_result, result end + def test_parse_pdu_net_ldap_connection_event + ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::BindResult + read_result = [2, ber] + @tcp_socket.should_receive(:read_ber).and_return(read_result) + + events = @service.subscribe "parse_pdu.net_ldap_connection" + + result = @connection.bind(method: :anon) + assert result.success?, "should be success" + + # a parse_pdu event + payload, result = events.pop + assert payload.has_key?(:pdu) + 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] + pdu = payload[:pdu] + assert_equal 0, pdu.result_code + end + def test_bind_net_ldap_connection_event ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult From 94e77aa96cdbe1689d3fbb9e924518f7ea6be3ec Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 17:31:25 -0700 Subject: [PATCH 188/435] Refactor/cleanup read error handling --- lib/net/ldap/connection.rb | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index a10b7774..2b2987e3 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -192,7 +192,8 @@ def bind_simple(auth) request_pkt = [msgid, request].to_ber_sequence write request_pkt - (pdu = read) or raise Net::LDAP::LdapError, "no bind result" + pdu = read + raise Net::LDAP::LdapError, "no bind result" unless pdu pdu end @@ -231,7 +232,9 @@ def bind_sasl(auth) request_pkt = [msgid, request].to_ber_sequence write request_pkt - (pdu = read) or raise Net::LDAP::LdapError, "no bind result" + pdu = read + raise Net::LDAP::LdapError, "no bind result" unless pdu + return pdu unless pdu.result_code == 14 # saslBindInProgress raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) @@ -409,7 +412,7 @@ def search(args = {}) result_pdu = nil controls = [] - while (pdu = read) + while pdu = read case pdu.app_tag when Net::LDAP::PDU::SearchReturnedData n_results += 1 @@ -515,7 +518,11 @@ def modify(args) pkt = [ next_msgid.to_ber, request ].to_ber_sequence write pkt - (pdu = read) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + pdu = read + + if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyResponse + raise Net::LDAP::LdapError, "response missing or invalid" + end pdu end @@ -538,9 +545,11 @@ def add(args) pkt = [next_msgid.to_ber, request].to_ber_sequence write pkt - (pdu = read) && - (pdu.app_tag == Net::LDAP::PDU::AddResponse) or + pdu = read + + if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse raise Net::LDAP::LdapError, "response missing or invalid" + end pdu end @@ -560,9 +569,11 @@ def rename(args) pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence write pkt - (pdu = read) && - (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or - raise Net::LDAP::LdapError.new( "response missing or invalid" ) + pdu = read + + if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyRDNResponse + raise Net::LDAP::LdapError.new "response missing or invalid" + end pdu end @@ -577,7 +588,11 @@ def delete(args) pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence write pkt - (pdu = read) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid" + pdu = read + + if !pdu || pdu.app_tag != Net::LDAP::PDU::DeleteResponse + raise Net::LDAP::LdapError, "response missing or invalid" + end pdu end From 128a9ead5e2f7cd34f8f5882b849d9f92de7230c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 17:47:20 -0700 Subject: [PATCH 189/435] Fix VM hostname --- test/support/vm/openldap/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/support/vm/openldap/Vagrantfile b/test/support/vm/openldap/Vagrantfile index 0aaa4feb..96233e92 100644 --- a/test/support/vm/openldap/Vagrantfile +++ b/test/support/vm/openldap/Vagrantfile @@ -5,7 +5,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.hostname = "freeipa.ghe.local" + config.vm.hostname = "rubyldap.com" config.vm.box = "hashicorp/precise64" From 4aea811b8ab146bb312473c8c5d4318c21246d57 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 18:43:49 -0700 Subject: [PATCH 190/435] Skip re-installing slapd et al --- script/install-openldap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/install-openldap b/script/install-openldap index cd9491c1..f8df42bf 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -5,7 +5,8 @@ set -x BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" -DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils +dpkg -s slapd time ldap-utils &>/dev/null ||\ + DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils sudo /etc/init.d/slapd stop From b9aaf67606b6774935a18ecaae92f11b1277067e Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 18:44:14 -0700 Subject: [PATCH 191/435] Setup retcode overlay Useful for testing out specific server responses in integration tests --- script/install-openldap | 2 + test/fixtures/openldap/retcode.ldif | 76 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 test/fixtures/openldap/retcode.ldif diff --git a/script/install-openldap b/script/install-openldap index f8df42bf..1e858a08 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -21,6 +21,8 @@ sudo cp -v ./DB_CONFIG /var/lib/ldap/DB_CONFIG sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/slapd.conf.ldif # Load memberof and ref-int overlays and configure them. sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/memberof.ldif +# Load retcode overlay and configure +sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/retcode.ldif # Add base domain. sudo slapadd -F /etc/ldap/slapd.d < Date: Wed, 15 Oct 2014 18:49:43 -0700 Subject: [PATCH 192/435] Revert re-install guard, debugging --- script/install-openldap | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/script/install-openldap b/script/install-openldap index 1e858a08..c8b23b79 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -5,8 +5,10 @@ set -x BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" -dpkg -s slapd time ldap-utils &>/dev/null ||\ - DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils +dpkg -s slapd time ldap-utils || true +echo $? + +DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils sudo /etc/init.d/slapd stop From 4f29d7dcbe7f7132c1bed78e5698fe507bf2d2f7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 15 Oct 2014 20:45:20 -0700 Subject: [PATCH 193/435] use flexmock for now since we're not moving away from flexmock just yet, I updated my tests to use flexmock to be consistent. cc @mtodd --- test/test_helper.rb | 1 - test/test_ldap_connection.rb | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index d5b30bca..f208977d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,7 +2,6 @@ require 'test/unit' require 'net/ldap' require 'flexmock/test_unit' -require 'minitest/mock' # Whether integration tests should be run. INTEGRATION = ENV.fetch("INTEGRATION", "skip") != "skip" diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index a9d20d8c..fa620111 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -44,15 +44,15 @@ def test_modify_ops_replace end def test_write - mock = Minitest::Mock.new - mock.expect(:write, true, [[1.to_ber, "request"].to_ber_sequence]) + mock = flexmock("socket") + mock.should_receive(:write).with([1.to_ber, "request"].to_ber_sequence).and_return(true) conn = Net::LDAP::Connection.new(:socket => mock) conn.send(:write, "request") end def test_write_with_controls - mock = Minitest::Mock.new - mock.expect(:write, true, [[1.to_ber, "request", "controls"].to_ber_sequence]) + mock = flexmock("socket") + mock.should_receive(:write).with([1.to_ber, "request", "controls"].to_ber_sequence).and_return(true) conn = Net::LDAP::Connection.new(:socket => mock) conn.send(:write, "request", "controls") end From 850729323e6762663341fef557df6998f75539b3 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 21:01:53 -0700 Subject: [PATCH 194/435] Revert revert re-install guard --- script/install-openldap | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/script/install-openldap b/script/install-openldap index c8b23b79..44ee0e31 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -5,10 +5,8 @@ set -x BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" -dpkg -s slapd time ldap-utils || true -echo $? - -DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils +dpkg -s slapd time ldap-utils ||\ + DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils sudo /etc/init.d/slapd stop From 2be8704f8173108efb06f36e096d7d9426bfc4d9 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 21:23:26 -0700 Subject: [PATCH 195/435] Add return code integration tests --- test/integration/test_return_codes.rb | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test/integration/test_return_codes.rb diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb new file mode 100644 index 00000000..60979eaf --- /dev/null +++ b/test/integration/test_return_codes.rb @@ -0,0 +1,38 @@ +require_relative '../test_helper' + +# NOTE: These tests depend on the OpenLDAP retcode overlay. +# See: section 12.12 http://www.openldap.org/doc/admin24/overlays.html + +class TestReturnCodeIntegration < LDAPIntegrationTestCase + def test_operations_error + refute @ldap.search(filter: "cn=operationsError", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert result = @ldap.get_operation_result + + assert_equal 1, result.code + assert_equal Net::LDAP::ResultStrings[1], result.message + end + + def test_protocol_error + refute @ldap.search(filter: "cn=protocolError", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert result = @ldap.get_operation_result + + assert_equal 2, result.code + assert_equal Net::LDAP::ResultStrings[2], result.message + end + + def test_time_limit_exceeded + refute @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert result = @ldap.get_operation_result + + assert_equal 3, result.code + assert_equal Net::LDAP::ResultStrings[3], result.message + end + + def test_size_limit_exceeded + refute @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert result = @ldap.get_operation_result + + assert_equal 4, result.code + assert_equal Net::LDAP::ResultStrings[4], result.message + end +end From 5b8dfd929b715580dc670e05e6d5136a46f0796f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 21:45:47 -0700 Subject: [PATCH 196/435] Add integration test for adding a person entry --- test/integration/test_add.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/integration/test_add.rb diff --git a/test/integration/test_add.rb b/test/integration/test_add.rb new file mode 100644 index 00000000..3cddb18a --- /dev/null +++ b/test/integration/test_add.rb @@ -0,0 +1,28 @@ +require_relative '../test_helper' + +class TestAddIntegration < LDAPIntegrationTestCase + def setup + super + @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" + + @dn = "uid=added-user1,ou=People,dc=rubyldap,dc=com" + end + + def test_add + attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: "added-user1", + cn: "added-user1", + sn: "added-user1", + mail: "added-user1@rubyldap.com" + } + + assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect + + assert result = @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject).first + end + + def teardown + @ldap.delete dn: @dn + end +end From cd3dc7f2356d0d6ea09c96baafd5059de011e147 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 22:04:12 -0700 Subject: [PATCH 197/435] Add delete integration test --- test/integration/test_delete.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/integration/test_delete.rb diff --git a/test/integration/test_delete.rb b/test/integration/test_delete.rb new file mode 100644 index 00000000..8df887dc --- /dev/null +++ b/test/integration/test_delete.rb @@ -0,0 +1,29 @@ +require_relative '../test_helper' + +class TestDeleteIntegration < LDAPIntegrationTestCase + def setup + super + @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" + + @dn = "uid=delete-user1,ou=People,dc=rubyldap,dc=com" + + attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: "delete-user1", + cn: "delete-user1", + sn: "delete-user1", + mail: "delete-user1@rubyldap.com" + } + assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect + assert @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + end + + def test_delete + assert @ldap.delete(dn: @dn), @ldap.get_operation_result.inspect + refute @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + + result = @ldap.get_operation_result + assert_equal 32, result.code + assert_equal Net::LDAP::ResultStrings[32], result.message + end +end From 74fe0701d019d087d5c3e8bb1b5ef7004cddfe0c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 22:09:51 -0700 Subject: [PATCH 198/435] Test Net::LDAP#open behavior --- test/integration/test_open.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/integration/test_open.rb diff --git a/test/integration/test_open.rb b/test/integration/test_open.rb new file mode 100644 index 00000000..ffa82216 --- /dev/null +++ b/test/integration/test_open.rb @@ -0,0 +1,23 @@ +require_relative '../test_helper' + +class TestBindIntegration < LDAPIntegrationTestCase + def test_binds_without_open + events = @service.subscribe "bind.net_ldap_connection" + + @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + + assert_equal 2, events.size + end + + def test_binds_with_open + events = @service.subscribe "bind.net_ldap_connection" + + @ldap.open do + @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + end + + assert_equal 1, events.size + end +end From f16a4ff609b0f6dc4ec4abe04e3d9adeed745708 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 15 Oct 2014 22:27:50 -0700 Subject: [PATCH 199/435] Add failing test for Net::LDAP#open with nested queries The nested query should match "user2", but with Net::LDAP#open, we see: <"user3"> expected but was <"user2">. And likewise with the outer search: <["user1", "user2"]> expected but was <["user1", "user3"]>. What's happening is that the nested query is being sent after the server has already sent more data to be read for the outer search, so when the inner search reads, it gets that result. And when it comes time for the outer search to handle the second results, it gets reads the next result off the wire, the result of the inner search. I was also able to get an infinite loop just by *always* performing an inner search instead of only searching on the first result. --- test/integration/test_open.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/integration/test_open.rb b/test/integration/test_open.rb index ffa82216..6d86f49a 100644 --- a/test/integration/test_open.rb +++ b/test/integration/test_open.rb @@ -20,4 +20,32 @@ def test_binds_with_open assert_equal 1, events.size end + + def test_nested_search_without_open + entries = [] + nested_entry = nil + + @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=rubyldap,dc=com") do |entry| + entries << entry.uid.first + nested_entry ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=rubyldap,dc=com").first + end + + assert_equal "user3", nested_entry.uid.first + assert_equal %w(user1 user2), entries + end + + def test_nested_search_with_open + entries = [] + nested_entry = nil + + @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 ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=rubyldap,dc=com").first + end + end + + assert_equal "user3", nested_entry.uid.first + assert_equal %w(user1 user2), entries + end end From b8071135a848ff18ffe3e5c96c102aececcfdaac Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 16 Oct 2014 10:58:27 -0700 Subject: [PATCH 200/435] missed a spot --- test/test_ldap_connection.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index fa620111..3068e680 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -58,9 +58,9 @@ def test_write_with_controls end def test_write_increments_msgid - mock = Minitest::Mock.new - mock.expect(:write, true, [[1.to_ber, "request1"].to_ber_sequence]) - mock.expect(:write, true, [[2.to_ber, "request2"].to_ber_sequence]) + mock = flexmock("socket") + mock.should_receive(:write).with([1.to_ber, "request1"].to_ber_sequence).and_return(true) + mock.should_receive(:write).with([2.to_ber, "request2"].to_ber_sequence).and_return(true) conn = Net::LDAP::Connection.new(:socket => mock) conn.send(:write, "request1") conn.send(:write, "request2") From f1e208cdb6d3fbc00a1181391a18ad3e334eb4dc Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 11:41:07 -0700 Subject: [PATCH 201/435] test search timeout parameter @mtodd is this a stupid test? The logic in Connection#search handles both writing the request and reading the response, making it really difficult to stub out. --- test/integration/test_search.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 77eea8c4..cff4cb89 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -24,4 +24,13 @@ def test_search_without_result assert result refute_equal entries, result end + + def test_search_timeout + events = @service.subscribe "search.net_ldap_connection" + + @ldap.search(:timeout => 1) + + payload, result = events.pop + assert_equal 1, payload[:timelimit] + end end From 4597aadc0856755a19e1fff52287ce855a07afed Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 11:45:13 -0700 Subject: [PATCH 202/435] fix whitespace --- lib/net/ldap/connection.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index c7150c21..a0d90a21 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -329,9 +329,8 @@ def search(args = {}) sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) - deref = args[:deref] || Net::LDAP::DerefAliases_Never - raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) - + deref = args[:deref] || Net::LDAP::DerefAliases_Never + raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) # An interesting value for the size limit would be close to A/D's # built-in page limit of 1000 records, but openLDAP newer than version From 0debe9bd901e33be9c18e407e78f6f32524fe7b1 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 13:00:23 -0700 Subject: [PATCH 203/435] test search attributes --- test/integration/test_search.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 77eea8c4..6c9701db 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -24,4 +24,10 @@ def test_search_without_result assert result refute_equal entries, result end + + def test_search_constrained_attributes + entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes: ["cn", "sn"]).first + assert_equal [:cn, :dn, :sn], entry.attribute_names.sort # :dn is always included + assert_empty entry[:mail] + end end From dac8a119a5b510d046376cf2a9373276734a33cd Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 13:06:00 -0700 Subject: [PATCH 204/435] add filter test --- test/integration/test_search.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 6c9701db..f32fdc81 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -4,7 +4,7 @@ class TestSearchIntegration < LDAPIntegrationTestCase def test_search entries = [] - result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com") do |entry| + result = @ldap.search(base: "dc=rubyldap,dc=com") do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end @@ -16,7 +16,7 @@ def test_search def test_search_without_result entries = [] - result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", return_result: false) do |entry| + result = @ldap.search(base: "dc=rubyldap,dc=com", return_result: false) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end @@ -25,6 +25,11 @@ def test_search_without_result refute_equal entries, result end + def test_search_filter + entries = @ldap.search(base: "dc=rubyldap,dc=com", filter: "(uid=user1)") + assert_equal 1, entries.size + end + def test_search_constrained_attributes entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes: ["cn", "sn"]).first assert_equal [:cn, :dn, :sn], entry.attribute_names.sort # :dn is always included From 0f51cb5a97a24e57f03d44a2f8804d0e10b5054a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 13:08:53 -0700 Subject: [PATCH 205/435] test search filter object --- test/integration/test_search.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index f32fdc81..59267308 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -25,11 +25,17 @@ def test_search_without_result refute_equal entries, result end - def test_search_filter + def test_search_filter_string entries = @ldap.search(base: "dc=rubyldap,dc=com", filter: "(uid=user1)") assert_equal 1, entries.size end + def test_search_filter_object + filter = Net::LDAP::Filter.eq("uid", "user1") | Net::LDAP::Filter.eq("uid", "user2") + entries = @ldap.search(base: "dc=rubyldap,dc=com", filter: filter) + assert_equal 2, entries.size + end + def test_search_constrained_attributes entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes: ["cn", "sn"]).first assert_equal [:cn, :dn, :sn], entry.attribute_names.sort # :dn is always included From 19b0b08035b9f1923c83989f5c366932a049322e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 13:36:42 -0700 Subject: [PATCH 206/435] test search size --- test/integration/test_search.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 59267308..6d1af7fd 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -41,4 +41,10 @@ def test_search_constrained_attributes assert_equal [:cn, :dn, :sn], entry.attribute_names.sort # :dn is always included assert_empty entry[:mail] end + + def test_search_size + entries = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) + + assert_equal 2, entries.size + end end From a604bef4cbba609393a43898f77e7d9d982862d4 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 17 Oct 2014 13:51:13 -0700 Subject: [PATCH 207/435] test attributes_only --- test/integration/test_search.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 6d1af7fd..e8db52b5 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -47,4 +47,10 @@ def test_search_size assert_equal 2, entries.size end + + def test_search_attributes_only + entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes_only: true).first + + assert_empty entry[:cn], "unexpected attribute value: #{entry[:cn]}" + end end From f638ea77ea79a749bb46203a531c57ef1b0ca640 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 17 Oct 2014 18:44:54 -0700 Subject: [PATCH 208/435] Skip failing searchSize integration test, add explanatory test This disables a failing test that won't pass without changing the behavior of Net::LDAP#search (and Net::LDAP::Connection#search). This is due to sizeLimitExceeded being treated as a failure instead of a deliberate termination of search results. Instead of returning the partial results, we currently return none. cc @jch @schaary --- test/integration/test_search.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index e8db52b5..cb1435d8 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -42,12 +42,40 @@ def test_search_constrained_attributes assert_empty entry[:mail] end + # http://tools.ietf.org/html/rfc4511#section-4.5.1.4 def test_search_size + skip "search treats sizeLimitExceeded response as failure" + entries = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) assert_equal 2, entries.size end + # See: test_search_size for what *should* work. + # + # This tests the currently broken behavior where searches are reported as + # failed when the size limit has been reached. This is broken since the + # sizeLimit parameter defines how many results to send back, and will result + # in a sizeLimitExceeded result in cases where there are more results than + # returned; not an error case, but also not a result code that is categorized + # as a non-error result (http://tools.ietf.org/html/rfc4511#appendix-A.1). + # The practical choice is to treat sizeLimitExceeded (and timeLimitExceeded) + # as successful search terminating messages. + def test_search_size_broken + entries = [] + refute @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) do |entry| + entries << entry.dn + end + + # reported as an "error" of sizeLimitExceeded + result = @ldap.get_operation_result + assert_equal 4, result.code + assert_equal Net::LDAP::ResultStrings[4], result.message + + # received the right number of results + assert_equal 2, entries.size + end + def test_search_attributes_only entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes_only: true).first From a47e3576f2b338f91f51b3bc9264235e4b3d112d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 17 Oct 2014 18:59:05 -0700 Subject: [PATCH 209/435] Block specificity strikes again --- test/integration/test_search.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index cb1435d8..fa4f78ed 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -63,9 +63,11 @@ def test_search_size # as successful search terminating messages. def test_search_size_broken entries = [] - refute @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) do |entry| + + returned = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) do |entry| entries << entry.dn end + refute returned # reported as an "error" of sizeLimitExceeded result = @ldap.get_operation_result From 70cb1f9696415fc7a299958ad661c6d165eefe46 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 03:00:11 -0700 Subject: [PATCH 210/435] Accept message_id as param to write --- lib/net/ldap/connection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index f0e5519d..b82f18c6 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -146,9 +146,9 @@ def read(syntax = Net::LDAP::AsnSyntax) # # Returns the return value from writing to the connection, which in some # cases is the Integer number of bytes written to the socket. - def write(request, controls = nil) + def write(request, controls = nil, message_id = next_msgid) instrument "write.net_ldap_connection" do |payload| - packet = [next_msgid.to_ber, request, controls].compact.to_ber_sequence + packet = [message_id.to_ber, request, controls].compact.to_ber_sequence payload[:content_length] = @conn.write(packet) end end From 8f4745d4a451cc45d2762fba5268332f2e8e4a0b Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 03:01:03 -0700 Subject: [PATCH 211/435] Pull queued messages first, queue messages unless ID matches --- lib/net/ldap/connection.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index b82f18c6..96166a64 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -356,6 +356,10 @@ def search(args = {}) result_pdu = nil n_results = 0 + @queue ||= {} + message_id = next_msgid + @queue[message_id] ||= [] + instrument "search.net_ldap_connection", :filter => search_filter, :base => search_base, @@ -403,12 +407,17 @@ def search(args = {}) controls << sort_control if sort_control controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) - write(request, controls) + write(request, controls, message_id) result_pdu = nil controls = [] - while pdu = read + while pdu = (@queue[message_id].shift || read) + if pdu.message_id != message_id + @queue[pdu.message_id].push pdu + next + end + case pdu.app_tag when Net::LDAP::PDU::SearchReturnedData n_results += 1 From 91618d679d6c644e49c7e62aa7490788ee6d0ce4 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 03:01:24 -0700 Subject: [PATCH 212/435] Include message ID in event payload --- lib/net/ldap/connection.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 96166a64..c11f4c3a 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -361,6 +361,7 @@ def search(args = {}) @queue[message_id] ||= [] instrument "search.net_ldap_connection", + :message_id => message_id, :filter => search_filter, :base => search_base, :scope => scope, From 9c4b45b59e9ea55842de215d8f7e7c28d417a662 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 03:12:02 -0700 Subject: [PATCH 213/435] Fix message_id in test --- test/test_ldap_connection.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 0c3c5f34..7b489e1f 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -185,16 +185,16 @@ def test_bind_net_ldap_connection_event def test_search_net_ldap_connection_event # search data - search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ + search_data_ber = Net::BER::BerIdentifiedArray.new([1, [ "uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local", [ ["uid", ["user1"]] ] ]]) search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData - search_data = [2, search_data_ber] + search_data = [1, search_data_ber] # search result (end of results) search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult - search_result = [2, search_result_ber] + search_result = [1, search_result_ber] @tcp_socket.should_receive(:read_ber).and_return(search_data). and_return(search_result) From acd676e3568a04676e0bf208188a6457070d7bb2 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 03:27:18 -0700 Subject: [PATCH 214/435] Extract queued_read(message_id) method --- lib/net/ldap/connection.rb | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index c11f4c3a..72c60578 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -111,6 +111,30 @@ def close @conn = nil end + # Internal: Reads messages by ID from a queue, falling back to reading from + # the connected socket until a message matching the ID is read. Any messages + # with mismatched IDs gets queued for subsequent reads by the origin of that + # message ID. + # + # Returns a Net::LDAP::PDU object or nil. + def queued_read(message_id) + if pdu = (@queue[message_id] || []).shift + return pdu + end + + while pdu = read + if pdu.message_id == message_id + return pdu + else + @queue[pdu.message_id].push pdu + + next + end + end + + pdu + end + # Internal: Reads and parses data from the configured connection. # # - syntax: the BER syntax to use to parse the read data with @@ -413,12 +437,7 @@ def search(args = {}) result_pdu = nil controls = [] - while pdu = (@queue[message_id].shift || read) - if pdu.message_id != message_id - @queue[pdu.message_id].push pdu - next - end - + while pdu = queued_read(message_id) case pdu.app_tag when Net::LDAP::PDU::SearchReturnedData n_results += 1 From 6cbb814db63874912858d309275be23e0a32a52f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 15:42:03 -0700 Subject: [PATCH 215/435] Extract message_queue accessor, documentation, cleanup --- lib/net/ldap/connection.rb | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 72c60578..758fe31c 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -118,16 +118,16 @@ def close # # Returns a Net::LDAP::PDU object or nil. def queued_read(message_id) - if pdu = (@queue[message_id] || []).shift + if pdu = message_queue[message_id].shift return pdu end + # read messages until we have a match for the given message_id while pdu = read if pdu.message_id == message_id return pdu else - @queue[pdu.message_id].push pdu - + message_queue[pdu.message_id].push pdu next end end @@ -135,6 +135,21 @@ def queued_read(message_id) pdu end + # Internal: The internal queue of messages, read from the socket, grouped by + # message ID. + # + # Used by `queued_read` to return messages sent by the server with the given + # ID. If no messages are queued for that ID, `queued_read` will `read` from + # the socket and queue messages that don't match the given ID for other + # readers. + # + # Returns the message queue Hash. + def message_queue + @message_queue ||= Hash.new do |hash, key| + hash[key] = [] + end + end + # Internal: Reads and parses data from the configured connection. # # - syntax: the BER syntax to use to parse the read data with @@ -380,9 +395,7 @@ def search(args = {}) result_pdu = nil n_results = 0 - @queue ||= {} message_id = next_msgid - @queue[message_id] ||= [] instrument "search.net_ldap_connection", :message_id => message_id, From 1e5916980f563f22c6af793fc9ec9f0882ce2c46 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 15:49:16 -0700 Subject: [PATCH 216/435] Clear search's message queue, instrument unread messages Shouldn't have unread messages but provide a way to measure it anyway. --- lib/net/ldap/connection.rb | 8 ++++++++ test/test_ldap_connection.rb | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 758fe31c..ac47e6e0 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -518,6 +518,14 @@ def search(args = {}) result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") end # instrument + ensure + # clean up message queue for this search + messages = message_queue.delete(message_id) + + unless messages.empty? + instrument "search_messages_unread.net_ldap_connection", + message_id: message_id, messages: messages + end end MODIFY_OPERATIONS = { #:nodoc: diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 7b489e1f..7ed75113 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -199,6 +199,7 @@ def test_search_net_ldap_connection_event and_return(search_result) events = @service.subscribe "search.net_ldap_connection" + unread = @service.subscribe "search_messages_unread.net_ldap_connection" result = @connection.search(filter: "(uid=user1)") assert result.success?, "should be success" @@ -209,5 +210,8 @@ def test_search_net_ldap_connection_event assert payload.has_key?(:filter) assert_equal "(uid=user1)", payload[:filter].to_s assert result + + # ensure no unread + assert unread.empty?, "should not have any leftover unread messages" end end From dc4db0e99880e856acfa37cd75177fd7fc6125ae Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 21:13:05 -0700 Subject: [PATCH 217/435] Cleanup Net::LDAP::Connection#search arg handling --- lib/net/ldap/connection.rb | 87 +++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index f0e5519d..26bcd56d 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -311,26 +311,37 @@ def encode_sort_controls(sort_definitions) # type-5 packet, which might never come. We need to support the time-limit # in the protocol. #++ - def search(args = {}) - search_filter = (args && args[:filter]) || - Net::LDAP::Filter.eq("objectclass", "*") - search_filter = Net::LDAP::Filter.construct(search_filter) if search_filter.is_a?(String) - search_base = (args && args[:base]) || "dc=example, dc=com" - search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber} - return_referrals = args && args[:return_referrals] == true - sizelimit = (args && args[:size].to_i) || 0 - raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0 - paged_searches_supported = (args && args[:paged_searches_supported]) - - attributes_only = (args and args[:attributes_only] == true) - scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree + def search(args = nil) + args ||= {} + + # filtering, scoping, search base + filter = args[:filter] || Net::LDAP::Filter.eq("objectClass", "*") + base = args[:base] + scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree + + # attr handling + attrs = Array(args[:attributes]) + attrs_only = args[:attributes_only] == true + + # references + refs = args[:return_referrals] == true + deref = args[:deref] || Net::LDAP::DerefAliases_Never + + # limiting, paging, sorting + size = args[:size].to_i + paged = args[:paged_searches_supported] + sort = args.fetch(:sort_controls, false) + + # arg validation + raise Net::LDAP::LdapError, "search base is required" unless base + raise Net::LDAP::LdapError, "invalid search-size" unless size >= 0 raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + raise Net::LDAP::LdapError, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) - sort_control = encode_sort_controls(args.fetch(:sort_controls){ false }) - - deref = args[:deref] || Net::LDAP::DerefAliases_Never - raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref) - + # arg transforms + filter = Net::LDAP::Filter.construct(filter) if filter.is_a?(String) + ber_attrs = attrs.map { |attr| attr.to_s.to_ber } + ber_sort = encode_sort_controls(sort) # An interesting value for the size limit would be close to A/D's # built-in page limit of 1000 records, but openLDAP newer than version @@ -357,35 +368,35 @@ def search(args = {}) n_results = 0 instrument "search.net_ldap_connection", - :filter => search_filter, - :base => search_base, - :scope => scope, - :limit => sizelimit, - :sort => sort_control, - :referrals => return_referrals, - :deref => deref, - :attributes => search_attributes do |payload| + filter: filter, + base: base, + scope: scope, + limit: size, + sort: sort, + referrals: refs, + deref: deref, + attributes: attrs do |payload| loop do # should collect this into a private helper to clarify the structure query_limit = 0 - if sizelimit > 0 - if paged_searches_supported - query_limit = (((sizelimit - n_results) < 126) ? (sizelimit - + if size > 0 + if paged + query_limit = (((size - n_results) < 126) ? (size - n_results) : 0) else - query_limit = sizelimit + query_limit = size end end request = [ - search_base.to_ber, + base.to_ber, scope.to_ber_enumerated, deref.to_ber_enumerated, query_limit.to_ber, # size limit 0.to_ber, - attributes_only.to_ber, - search_filter.to_ber, - search_attributes.to_ber_sequence + attrs_only.to_ber, + filter.to_ber, + ber_attrs.to_ber_sequence ].to_ber_appsequence(3) # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory @@ -399,8 +410,8 @@ def search(args = {}) # Criticality MUST be false to interoperate with normal LDAPs. false.to_ber, rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber - ].to_ber_sequence if paged_searches_supported - controls << sort_control if sort_control + ].to_ber_sequence if paged + controls << ber_sort if ber_sort controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) write(request, controls) @@ -414,7 +425,7 @@ def search(args = {}) n_results += 1 yield pdu.search_entry if block_given? when Net::LDAP::PDU::SearchResultReferral - if return_referrals + if refs if block_given? se = Net::LDAP::Entry.new se[:search_referrals] = (pdu.search_referrals || []) @@ -424,7 +435,7 @@ def search(args = {}) when Net::LDAP::PDU::SearchResult result_pdu = pdu controls = pdu.result_controls - if return_referrals && pdu.result_code == 10 + if refs && pdu.result_code == 10 if block_given? se = Net::LDAP::Entry.new se[:search_referrals] = (pdu.search_referrals || []) From 549b1d94bd48aeb24e93b4490047d9d2230303cd Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 21:13:48 -0700 Subject: [PATCH 218/435] Skip fixture add if exists This can happen if a failure prevents this from being cleaned up properly in the last run. --- test/integration/test_delete.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/test_delete.rb b/test/integration/test_delete.rb index 8df887dc..9cd9972b 100644 --- a/test/integration/test_delete.rb +++ b/test/integration/test_delete.rb @@ -14,7 +14,9 @@ def setup sn: "delete-user1", mail: "delete-user1@rubyldap.com" } - assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect + unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect + end assert @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) end From 401909371715b62db02b7b4802f761e6ec7b2c6e Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 21:14:19 -0700 Subject: [PATCH 219/435] Include required search base, fix test DN --- test/test_ldap_connection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 0c3c5f34..1067534c 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -186,7 +186,7 @@ def test_bind_net_ldap_connection_event def test_search_net_ldap_connection_event # search data search_data_ber = Net::BER::BerIdentifiedArray.new([2, [ - "uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local", + "uid=user1,ou=People,dc=rubyldap,dc=com", [ ["uid", ["user1"]] ] ]]) search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData @@ -200,7 +200,7 @@ def test_search_net_ldap_connection_event events = @service.subscribe "search.net_ldap_connection" - result = @connection.search(filter: "(uid=user1)") + result = @connection.search(filter: "(uid=user1)", base: "ou=People,dc=rubyldap,dc=com") assert result.success?, "should be success" # a search event From 74bb8b3680524a1456a29fbeb92ddf8d25e23896 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 19 Oct 2014 21:47:33 -0700 Subject: [PATCH 220/435] Document search args with relevant RFC sections --- lib/net/ldap/connection.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 26bcd56d..ce4c5130 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -315,19 +315,27 @@ def search(args = nil) args ||= {} # filtering, scoping, search base + # filter: https://tools.ietf.org/html/rfc4511#section-4.5.1.7 + # base: https://tools.ietf.org/html/rfc4511#section-4.5.1.1 + # scope: https://tools.ietf.org/html/rfc4511#section-4.5.1.2 filter = args[:filter] || Net::LDAP::Filter.eq("objectClass", "*") base = args[:base] scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree # attr handling + # attrs: https://tools.ietf.org/html/rfc4511#section-4.5.1.8 + # attrs_only: https://tools.ietf.org/html/rfc4511#section-4.5.1.6 attrs = Array(args[:attributes]) attrs_only = args[:attributes_only] == true # references + # refs: https://tools.ietf.org/html/rfc4511#section-4.5.3 + # deref: https://tools.ietf.org/html/rfc4511#section-4.5.1.3 refs = args[:return_referrals] == true deref = args[:deref] || Net::LDAP::DerefAliases_Never # limiting, paging, sorting + # size: https://tools.ietf.org/html/rfc4511#section-4.5.1.4 size = args[:size].to_i paged = args[:paged_searches_supported] sort = args.fetch(:sort_controls, false) From 2a2bf1a63caefc146f4161c0c6dbf1dadcea8842 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 18:14:37 +0300 Subject: [PATCH 221/435] Fix size option for ldap.search method Signed-off-by: Dmitriy Zaporozhets --- lib/net/ldap.rb | 13 ++++++++++++- test/test_ldap.rb | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 4faaad7b..d9c48623 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -678,7 +678,18 @@ def search(args = {}) end if return_result_set - (!@result.nil? && @result.result_code == 0) ? result_set : nil + unless @result.nil? + case @result.result_code + when 0 + # everything good + result_set + when 4 + # LDAP: Size limit exceeded + # This happens when we use size option and results are truncated + # Still we need to return user results + result_set + end + end else @result.success? end diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 5984aba7..ceb8c1a0 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -40,4 +40,20 @@ def test_instrument_search assert_equal [entry], payload[:result] assert_equal "(uid=user1)", payload[:filter] end + + def test_instrument_search_with_size + events = @service.subscribe "search.net_ldap" + + flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + flexmock(@connection).should_receive(:search).with(Hash, Proc). + yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). + and_return(flexmock(:search_result, :success? => true, :result_code => 4)) + + refute_nil @subject.search(:filter => "(uid=user1)", :size => 1) + + payload, result = events.pop + assert_equal [entry], result + assert_equal [entry], payload[:result] + assert_equal "(uid=user1)", payload[:filter] + end end From 40bcac31107595e2cc510f1e7a93a5fce53259f5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 19:18:12 +0300 Subject: [PATCH 222/435] Fix test for ldap.search return codes Signed-off-by: Dmitriy Zaporozhets --- test/integration/test_return_codes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb index 60979eaf..9dadcdd0 100644 --- a/test/integration/test_return_codes.rb +++ b/test/integration/test_return_codes.rb @@ -29,7 +29,7 @@ def test_time_limit_exceeded end def test_size_limit_exceeded - refute @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result assert_equal 4, result.code From 75cda5a1aba919a766e92f703bd31568dd446044 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 19:25:35 +0300 Subject: [PATCH 223/435] Remove unnecessary assert in ldap.search return code test Signed-off-by: Dmitriy Zaporozhets --- test/integration/test_return_codes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb index 9dadcdd0..d3a6758b 100644 --- a/test/integration/test_return_codes.rb +++ b/test/integration/test_return_codes.rb @@ -29,7 +29,7 @@ def test_time_limit_exceeded end def test_size_limit_exceeded - assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result assert_equal 4, result.code From 9adc5876a4a0e59612f3c92a7c8bdf60a76f22ec Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 19:28:49 +0300 Subject: [PATCH 224/435] Avoid using magic number in ldap.search Signed-off-by: Dmitriy Zaporozhets --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index d9c48623..d77f2a7e 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -683,7 +683,7 @@ def search(args = {}) when 0 # everything good result_set - when 4 + when ResultStrings.key("Size Limit Exceeded") # LDAP: Size limit exceeded # This happens when we use size option and results are truncated # Still we need to return user results From e8e0e282b9c23378fe39936f1ad98df4ae51f0ae Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 19:37:41 +0300 Subject: [PATCH 225/435] Avoid magic number in success case of ldap search Signed-off-by: Dmitriy Zaporozhets --- lib/net/ldap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index d77f2a7e..749f1e0d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -680,7 +680,7 @@ def search(args = {}) if return_result_set unless @result.nil? case @result.result_code - when 0 + when ResultStrings.key("Success") # everything good result_set when ResultStrings.key("Size Limit Exceeded") From b0bc21554d60d24039040aae20cf1a9700de941c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 20:30:22 +0300 Subject: [PATCH 226/435] Add additional integration test for ldap.search with result Signed-off-by: Dmitriy Zaporozhets --- test/integration/test_search.rb | 12 ++++++++++++ test/test_ldap.rb | 1 + 2 files changed, 13 insertions(+) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 77eea8c4..04d75b01 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -24,4 +24,16 @@ def test_search_without_result assert result refute_equal entries, result end + + def test_search_with_size + entries = [] + + result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", return_result: false, size: 1) do |entry| + assert_kind_of Net::LDAP::Entry, entry + entries << entry + end + + refute entries.empty? + assert_equal entries, result + end end diff --git a/test/test_ldap.rb b/test/test_ldap.rb index ceb8c1a0..6568a47c 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -55,5 +55,6 @@ def test_instrument_search_with_size assert_equal [entry], result assert_equal [entry], payload[:result] assert_equal "(uid=user1)", payload[:filter] + assert_equal result.size, payload[:size] end end From 0536b42d47570240c0ae680b876967e077ea3557 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 10:46:35 -0700 Subject: [PATCH 227/435] Add explanatory comment --- lib/net/ldap/connection.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index ad93d16d..0898573c 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -541,6 +541,8 @@ def search(args = nil) # clean up message queue for this search messages = message_queue.delete(message_id) + # in the exceptional case some messages were *not* consumed from the queue, + # instrument the event but do not fail. unless messages.empty? instrument "search_messages_unread.net_ldap_connection", message_id: message_id, messages: messages From f3a25154d14f98c0df118728ac12da34f9c54065 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 21 Oct 2014 20:47:57 +0300 Subject: [PATCH 228/435] Fix test_search_with_size case Signed-off-by: Dmitriy Zaporozhets --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 04d75b01..d5616e16 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -28,7 +28,7 @@ def test_search_without_result def test_search_with_size entries = [] - result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", return_result: false, size: 1) do |entry| + result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", size: 1) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end From b0828d49d391cfa5dd01135b40dab3c999a9acae Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 11:12:47 -0700 Subject: [PATCH 229/435] change search instrumentation field s/limit/size/ matches up with how `time` param works. @mtodd you okay with this? --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index b66545dc..538c3f4a 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -381,7 +381,7 @@ def search(args = nil) filter: filter, base: base, scope: scope, - limit: size, + size: size, time: time, sort: sort, referrals: refs, From f8520845586212ac90234694fad7d4be22dcc58c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 11:15:03 -0700 Subject: [PATCH 230/435] missed a spot during merge --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 538c3f4a..e0ec33c7 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -404,7 +404,7 @@ def search(args = nil) scope.to_ber_enumerated, deref.to_ber_enumerated, query_limit.to_ber, # size limit - timelimit.to_ber, + time.to_ber, attrs_only.to_ber, filter.to_ber, ber_attrs.to_ber_sequence From 8c111230e106b92f01e288ad7284c59732c4004e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 11:15:44 -0700 Subject: [PATCH 231/435] rename timelimit to time --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index cff4cb89..5d571dc2 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -31,6 +31,6 @@ def test_search_timeout @ldap.search(:timeout => 1) payload, result = events.pop - assert_equal 1, payload[:timelimit] + assert_equal 1, payload[:time] end end From 6842f331bb8c8f2074075aef521318a9563b21c3 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 11:18:01 -0700 Subject: [PATCH 232/435] parameter is named time --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 5d571dc2..3a13120a 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -28,7 +28,7 @@ def test_search_without_result def test_search_timeout events = @service.subscribe "search.net_ldap_connection" - @ldap.search(:timeout => 1) + @ldap.search(:time => 5) payload, result = events.pop assert_equal 1, payload[:time] From e5e47a449e0fcb23f33f855c8896cce3d48b83ab Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 14:38:05 -0700 Subject: [PATCH 233/435] add base to search --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 3a13120a..92174233 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -28,7 +28,7 @@ def test_search_without_result def test_search_timeout events = @service.subscribe "search.net_ldap_connection" - @ldap.search(:time => 5) + @ldap.search(base: "dc=rubyldap,dc=com", time: 5) payload, result = events.pop assert_equal 1, payload[:time] From 4358f9ceb9b488031b21bef287ecf597932dd922 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 19:04:18 -0700 Subject: [PATCH 234/435] failing test for time limit search --- test/integration/test_search.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 119ac6d9..079e1c90 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -26,9 +26,13 @@ def test_search_without_result end def test_search_timeout + entries = [] events = @service.subscribe "search.net_ldap_connection" - result = @ldap.search(base: "dc=rubyldap,dc=com", time: 5) + result = @ldap.search(base: "dc=rubyldap,dc=com", time: 5) do |entry| + assert_kind_of Net::LDAP::Entry, entry + entries << entry + end payload, result = events.pop assert_equal 5, payload[:time] From 17d3201e4b834bca23b1f31ad4a8e61ca183f65e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 21 Oct 2014 19:10:05 -0700 Subject: [PATCH 235/435] return partial results when exceeding search time limit --- lib/net/ldap.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 2ad6e3a3..f19fd837 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -684,8 +684,8 @@ def search(args = {}) when ResultStrings.key("Success") # everything good result_set - when ResultStrings.key("Size Limit Exceeded") - # LDAP: Size limit exceeded + when ResultStrings.key("Size Limit Exceeded"), ResultStrings.key("Time Limit Exceeded") + # LDAP: Size/Time limit exceeded # This happens when we use size option and results are truncated # Still we need to return user results result_set From a460d4a4251df4a255842a1981a1a4f4f2898416 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 19:36:47 -0700 Subject: [PATCH 236/435] Discard unneeded event data Name conflicted with real test data --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 079e1c90..919cdfbc 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -34,7 +34,7 @@ def test_search_timeout entries << entry end - payload, result = events.pop + payload, _ = events.pop assert_equal 5, payload[:time] assert_equal entries, result end From 69c7593a9262937025aacad90200d5eb6fbc9a79 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 20:13:12 -0700 Subject: [PATCH 237/435] Assert search returns a truthy value --- test/integration/test_return_codes.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb index d3a6758b..df93ddf0 100644 --- a/test/integration/test_return_codes.rb +++ b/test/integration/test_return_codes.rb @@ -21,7 +21,7 @@ def test_protocol_error end def test_time_limit_exceeded - refute @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result assert_equal 3, result.code @@ -29,7 +29,7 @@ def test_time_limit_exceeded end def test_size_limit_exceeded - @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result assert_equal 4, result.code From 450bed62acd5ec6797d3011cdea37c9b804ceb48 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 21:22:22 -0700 Subject: [PATCH 238/435] Add explicit result code constants, update string mapping --- lib/net/ldap.rb | 118 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 22 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index f19fd837..545d451c 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -321,29 +321,103 @@ class LdapError < StandardError; end StartTlsOid = "1.3.6.1.4.1.1466.20037" + # https://tools.ietf.org/html/rfc4511#section-4.1.9 + # https://tools.ietf.org/html/rfc4511#appendix-A + ResultCodeSuccess = 0 + ResultCodeOperationsError = 1 + ResultCodeProtocolError = 2 + ResultCodeTimeLimitExceeded = 3 + ResultCodeSizeLimitExceeded = 4 + ResultCodeCompareFalse = 5 + ResultCodeCompareTrue = 6 + ResultCodeAuthMethodNotSupported = 7 + ResultCodeStrongerAuthRequired = 8 + ResultCodeReferral = 10 + ResultCodeAdminLimitExceeded = 11 + ResultCodeUnavailableCriticalExtension = 12 + ResultCodeConfidentialityRequired = 13 + ResultCodeSaslBindInProgress = 14 + ResultCodeNoSuchAttribute = 16 + ResultCodeUndefinedAttributeType = 17 + ResultCodeInappropriateMatching = 18 + ResultCodeConstraintViolation = 19 + ResultCodeAttributeOrValueExists = 20 + ResultCodeInvalidAttributeSyntax = 21 + ResultCodeNoSuchObject = 32 + ResultCodeAliasProblem = 33 + ResultCodeInvalidDNSyntax = 34 + ResultCodeAliasDereferencingProblem = 36 + ResultCodeInappropriateAuthentication = 48 + ResultCodeInvalidCredentials = 49 + ResultCodeInsufficientAccessRights = 50 + ResultCodeBusy = 51 + ResultCodeUnavailable = 52 + ResultCodeUnwillingToPerform = 53 + ResultCodeNamingViolation = 64 + ResultCodeObjectClassViolation = 65 + ResultCodeNotAllowedOnNonLeaf = 66 + ResultCodeNotAllowedOnRDN = 67 + ResultCodeEntryAlreadyExists = 68 + ResultCodeObjectClassModsProhibited = 69 + ResultCodeAffectsMultipleDSAs = 71 + ResultCodeOther = 80 + + # https://tools.ietf.org/html/rfc4511#appendix-A.1 + ResultCodesNonError = [ + ResultCodeSuccess, + ResultCodeCompareFalse, + ResultCodeCompareTrue, + ResultCodeReferral, + ResultCodeSaslBindInProgress + ] + + # nonstandard list of "successful" result codes for searches + ResultCodesSearchSuccess = [ + ResultCodeSuccess, + ResultCodeTimeLimitExceeded, + ResultCodeSizeLimitExceeded + ] + + # map of result code to human message ResultStrings = { - 0 => "Success", - 1 => "Operations Error", - 2 => "Protocol Error", - 3 => "Time Limit Exceeded", - 4 => "Size Limit Exceeded", - 10 => "Referral", - 12 => "Unavailable crtical extension", - 14 => "saslBindInProgress", - 16 => "No Such Attribute", - 17 => "Undefined Attribute Type", - 19 => "Constraint Violation", - 20 => "Attribute or Value Exists", - 32 => "No Such Object", - 34 => "Invalid DN Syntax", - 48 => "Inappropriate Authentication", - 49 => "Invalid Credentials", - 50 => "Insufficient Access Rights", - 51 => "Busy", - 52 => "Unavailable", - 53 => "Unwilling to perform", - 65 => "Object Class Violation", - 68 => "Entry Already Exists" + ResultCodeSuccess => "Success", + ResultCodeOperationsError => "Operations Error", + ResultCodeProtocolError => "Protocol Error", + ResultCodeTimeLimitExceeded => "Time Limit Exceeded", + ResultCodeSizeLimitExceeded => "Size Limit Exceeded", + ResultCodeCompareFalse => "False Comparison", + ResultCodeCompareTrue => "True Comparison", + ResultCodeAuthMethodNotSupported => "Auth Method Not Supported", + ResultCodeStrongerAuthRequired => "Stronger Auth Needed", + ResultCodeReferral => "Referral", + ResultCodeAdminLimitExceeded => "Admin Limit Exceeded", + ResultCodeUnavailableCriticalExtension => "Unavailable crtical extension", + ResultCodeConfidentialityRequired => "Confidentiality Required", + ResultCodeSaslBindInProgress => "saslBindInProgress", + ResultCodeNoSuchAttribute => "No Such Attribute", + ResultCodeUndefinedAttributeType => "Undefined Attribute Type", + ResultCodeInappropriateMatching => "Inappropriate Matching", + ResultCodeConstraintViolation => "Constraint Violation", + ResultCodeAttributeOrValueExists => "Attribute or Value Exists", + ResultCodeInvalidAttributeSyntax => "Invalide Attribute Syntax", + ResultCodeNoSuchObject => "No Such Object", + ResultCodeAliasProblem => "Alias Problem", + ResultCodeInvalidDNSyntax => "Invalid DN Syntax", + ResultCodeAliasDereferencingProblem => "Alias Dereferencing Problem", + ResultCodeInappropriateAuthentication => "Inappropriate Authentication", + ResultCodeInvalidCredentials => "Invalid Credentials", + ResultCodeInsufficientAccessRights => "Insufficient Access Rights", + ResultCodeBusy => "Busy", + ResultCodeUnavailable => "Unavailable", + ResultCodeUnwillingToPerform => "Unwilling to perform", + ResultCodeNamingViolation => "Naming Violation", + ResultCodeObjectClassViolation => "Object Class Violation", + ResultCodeNotAllowedOnNonLeaf => "Not Allowed On Non-Leaf", + ResultCodeNotAllowedOnRDN => "Not Allowed On RDN", + ResultCodeEntryAlreadyExists => "Entry Already Exists", + ResultCodeObjectClassModsProhibited => "ObjectClass Modifications Prohibited", + ResultCodeAffectsMultipleDSAs => "Affects Multiple DSAs", + ResultCodeOther => "Other" } module LDAPControls From 89a4f8bde60e9f9e5d28196ecbf3e6564e436dc3 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 21:23:01 -0700 Subject: [PATCH 239/435] Replace magic number with result code constant --- lib/net/ldap.rb | 12 ++++++------ lib/net/ldap/connection.rb | 8 ++++---- lib/net/ldap/pdu.rb | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 545d451c..e19b67d2 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -623,7 +623,7 @@ def get_operation_result elsif result os.code = result else - os.code = 0 + os.code = Net::LDAP::ResultCodeSuccess end os.message = Net::LDAP.result2string(os.code) os @@ -741,7 +741,7 @@ def search(args = {}) :port => @port, :encryption => @encryption, :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess @result = conn.search(args) { |entry| result_set << entry if result_set yield entry if block_given? @@ -947,7 +947,7 @@ def add(args) :port => @port, :encryption => @encryption, :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess @result = conn.add(args) end ensure @@ -1051,7 +1051,7 @@ def modify(args) :port => @port, :encryption => @encryption, :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess @result = conn.modify(args) end ensure @@ -1128,7 +1128,7 @@ def rename(args) :port => @port, :encryption => @encryption, :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess @result = conn.rename(args) end ensure @@ -1161,7 +1161,7 @@ def delete(args) :port => @port, :encryption => @encryption, :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == 0 + if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess @result = conn.delete(args) end ensure diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index cafa30d4..4efe14d8 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -271,7 +271,7 @@ def bind_sasl(auth) pdu = read raise Net::LDAP::LdapError, "no bind result" unless pdu - return pdu unless pdu.result_code == 14 # saslBindInProgress + return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) cred = chall.call(pdu.result_server_sasl_creds) @@ -488,7 +488,7 @@ def search(args = nil) when Net::LDAP::PDU::SearchResult result_pdu = pdu controls = pdu.result_controls - if refs && pdu.result_code == 10 + if refs && pdu.result_code == Net::LDAP::ResultCodeReferral if block_given? se = Net::LDAP::Entry.new se[:search_referrals] = (pdu.search_referrals || []) @@ -516,7 +516,7 @@ def search(args = nil) # of type OCTET STRING, covered in the default syntax supported by # read_ber, so I guess we're ok. more_pages = false - if result_pdu.result_code == 0 and controls + if result_pdu.result_code == Net::LDAP::ResultCodeSuccess and controls controls.each do |c| if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS # just in case some bogus server sends us more than 1 of these. @@ -538,7 +538,7 @@ def search(args = nil) # track total result count payload[:result_count] = n_results - result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search") + result_pdu || OpenStruct.new(:status => :failure, :result_code => Net::LDAP::ResultCodeOperationsError, :message => "Invalid search") end # instrument ensure # clean up message queue for this search diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 26d4f8b8..51dcac2b 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -152,7 +152,7 @@ def parse_ldap_result(sequence) :matchedDN => sequence[1], :errorMessage => sequence[2] } - parse_search_referral(sequence[3]) if @ldap_result[:resultCode] == 10 + parse_search_referral(sequence[3]) if @ldap_result[:resultCode] == Net::LDAP::ResultCodeReferral end private :parse_ldap_result From 63eae4aa9c1aed67fc67e752694f6353037d7378 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 21:23:44 -0700 Subject: [PATCH 240/435] Check specific search success result codes --- lib/net/ldap.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index e19b67d2..ac07d901 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -754,14 +754,7 @@ def search(args = {}) if return_result_set unless @result.nil? - case @result.result_code - when ResultStrings.key("Success") - # everything good - result_set - when ResultStrings.key("Size Limit Exceeded"), ResultStrings.key("Time Limit Exceeded") - # LDAP: Size/Time limit exceeded - # This happens when we use size option and results are truncated - # Still we need to return user results + if ResultCodesSearchSuccess.include?(@result.result_code) result_set end end From 2d494c365b0a76f1850fa1a9457c05faedd586cd Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 21:24:02 -0700 Subject: [PATCH 241/435] Consider non-error result codes as successful --- lib/net/ldap/pdu.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 51dcac2b..2c3d5116 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -125,7 +125,7 @@ def result_code(code = :resultCode) end def status - result_code == 0 ? :success : :failure + Net::LDAP::ResultCodesNonError.include?(result_code) ? :success : :failure end def success? From 14b2d14ca3e26b52ae44763d41854ff0e3dd9e82 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 21 Oct 2014 21:48:36 -0700 Subject: [PATCH 242/435] Use result code constants in tests --- test/integration/test_bind.rb | 4 ++-- test/integration/test_delete.rb | 4 ++-- test/integration/test_return_codes.rb | 16 ++++++++-------- test/test_ldap.rb | 8 ++++---- test/test_ldap_connection.rb | 16 ++++++++-------- test/test_search.rb | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index 5ec1b63f..afadb4c8 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -9,8 +9,8 @@ def test_bind_anonymous_fail refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect result = @ldap.get_operation_result - assert_equal 53, result.code - assert_equal "Unwilling to perform", result.message + assert_equal Net::LDAP::ResultCodeUnwillingToPerform, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeUnwillingToPerform], result.message assert_equal "unauthenticated bind (DN with no password) disallowed", result.error_message assert_equal "", result.matched_dn diff --git a/test/integration/test_delete.rb b/test/integration/test_delete.rb index 9cd9972b..355df7b9 100644 --- a/test/integration/test_delete.rb +++ b/test/integration/test_delete.rb @@ -25,7 +25,7 @@ def test_delete refute @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) result = @ldap.get_operation_result - assert_equal 32, result.code - assert_equal Net::LDAP::ResultStrings[32], result.message + assert_equal Net::LDAP::ResultCodeNoSuchObject, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeNoSuchObject], result.message end end diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb index df93ddf0..0e381a0a 100644 --- a/test/integration/test_return_codes.rb +++ b/test/integration/test_return_codes.rb @@ -8,31 +8,31 @@ def test_operations_error refute @ldap.search(filter: "cn=operationsError", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result - assert_equal 1, result.code - assert_equal Net::LDAP::ResultStrings[1], result.message + assert_equal Net::LDAP::ResultCodeOperationsError, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeOperationsError], result.message end def test_protocol_error refute @ldap.search(filter: "cn=protocolError", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result - assert_equal 2, result.code - assert_equal Net::LDAP::ResultStrings[2], result.message + assert_equal Net::LDAP::ResultCodeProtocolError, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeProtocolError], result.message end def test_time_limit_exceeded assert @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result - assert_equal 3, result.code - assert_equal Net::LDAP::ResultStrings[3], result.message + assert_equal Net::LDAP::ResultCodeTimeLimitExceeded, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeTimeLimitExceeded], result.message end def test_size_limit_exceeded assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") assert result = @ldap.get_operation_result - assert_equal 4, result.code - assert_equal Net::LDAP::ResultStrings[4], result.message + assert_equal Net::LDAP::ResultCodeSizeLimitExceeded, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeSizeLimitExceeded], result.message end end diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 6568a47c..9704b346 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -28,10 +28,10 @@ def test_instrument_bind def test_instrument_search events = @service.subscribe "search.net_ldap" - flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess)) flexmock(@connection).should_receive(:search).with(Hash, Proc). yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). - and_return(flexmock(:search_result, :success? => true, :result_code => 0)) + and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSuccess)) refute_nil @subject.search(:filter => "(uid=user1)") @@ -44,10 +44,10 @@ def test_instrument_search def test_instrument_search_with_size events = @service.subscribe "search.net_ldap" - flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0)) + flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess)) flexmock(@connection).should_receive(:search).with(Hash, Proc). yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). - and_return(flexmock(:search_result, :success? => true, :result_code => 4)) + and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSizeLimitExceeded)) refute_nil @subject.search(:filter => "(uid=user1)", :size => 1) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 35b3b4f6..46e535ff 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -77,7 +77,7 @@ def setup end def test_error_failed_operation - ber = Net::BER::BerIdentifiedArray.new([53, "", "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 = 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]) @@ -87,7 +87,7 @@ def test_error_failed_operation end def test_no_error_on_success - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + 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]) @@ -111,7 +111,7 @@ def setup end def test_write_net_ldap_connection_event - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) @@ -128,7 +128,7 @@ def test_write_net_ldap_connection_event end def test_read_net_ldap_connection_event - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) @@ -145,7 +145,7 @@ def test_read_net_ldap_connection_event end def test_parse_pdu_net_ldap_connection_event - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult read_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) @@ -163,11 +163,11 @@ def test_parse_pdu_net_ldap_connection_event assert_equal Net::LDAP::PDU::BindResult, payload[:app_tag] assert_equal 2, payload[:message_id] pdu = payload[:pdu] - assert_equal 0, pdu.result_code + assert_equal Net::LDAP::ResultCodeSuccess, pdu.result_code end def test_bind_net_ldap_connection_event - ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult bind_result = [2, ber] @tcp_socket.should_receive(:read_ber).and_return(bind_result) @@ -192,7 +192,7 @@ def test_search_net_ldap_connection_event search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData search_data = [1, search_data_ber] # search result (end of results) - search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""]) + search_result_ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult search_result = [1, search_result_ber] @tcp_socket.should_receive(:read_ber).and_return(search_data). diff --git a/test/test_search.rb b/test/test_search.rb index 1481aa06..e349d0b8 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -4,7 +4,7 @@ class TestSearch < Test::Unit::TestCase class FakeConnection def search(args) - OpenStruct.new(:result_code => 1, :message => "error", :success? => false) + OpenStruct.new(:result_code => Net::LDAP::ResultCodeOperationsError, :message => "error", :success? => false) end end From 480bd1706a19f2c9f0525d9c241f3bb126c45361 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 00:18:25 -0700 Subject: [PATCH 243/435] Encode true as xFF According to the spec: http://tools.ietf.org/html/rfc4511#section-5.1 --- lib/net/ber/core_ext/true_class.rb | 5 ++--- test/ber/test_ber.rb | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/net/ber/core_ext/true_class.rb b/lib/net/ber/core_ext/true_class.rb index ac66c926..d6a8c8f7 100644 --- a/lib/net/ber/core_ext/true_class.rb +++ b/lib/net/ber/core_ext/true_class.rb @@ -5,8 +5,7 @@ module Net::BER::Extensions::TrueClass ## # Converts +true+ to the BER wireline representation of +true+. def to_ber - # 20100319 AZ: Note that this may not be the completely correct value, - # per some test documentation. We need to determine the truth of this. - "\001\001\001" + # http://tools.ietf.org/html/rfc4511#section-5.1 + "\001\001\xFF" end end diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 6f641bb4..c2b0ef17 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -12,8 +12,9 @@ def test_array assert_equal ary, encoded_ary.read_ber end + # http://tools.ietf.org/html/rfc4511#section-5.1 def test_true - assert_equal "\x01\x01\x01", true.to_ber + assert_equal "\x01\x01\xFF", true.to_ber end def test_false From ab7b60c0d5508dfea24cbe30491719fceb833d66 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 00:32:29 -0700 Subject: [PATCH 244/435] Force encoding to ASCII-8BIT We allow this since the library requires Ruby 1.9+ --- lib/net/ber/core_ext/true_class.rb | 2 +- test/ber/test_ber.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ber/core_ext/true_class.rb b/lib/net/ber/core_ext/true_class.rb index d6a8c8f7..bf199d1e 100644 --- a/lib/net/ber/core_ext/true_class.rb +++ b/lib/net/ber/core_ext/true_class.rb @@ -6,6 +6,6 @@ module Net::BER::Extensions::TrueClass # Converts +true+ to the BER wireline representation of +true+. def to_ber # http://tools.ietf.org/html/rfc4511#section-5.1 - "\001\001\xFF" + "\001\001\xFF".force_encoding("ASCII-8BIT") end end diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index c2b0ef17..7eade7c2 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -14,7 +14,7 @@ def test_array # http://tools.ietf.org/html/rfc4511#section-5.1 def test_true - assert_equal "\x01\x01\xFF", true.to_ber + assert_equal "\x01\x01\xFF".b, true.to_ber end def test_false From bb798c4d77defc08d17a4565be9b26e855a00d3b Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:26:48 -0700 Subject: [PATCH 245/435] 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 246/435] 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 811aad8e783c7676185f46e00209121182eb41f0 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:46:12 -0700 Subject: [PATCH 247/435] Add request app ID, document relevant spec sections --- lib/net/ldap/pdu.rb | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 2c3d5116..f2cd304c 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -18,22 +18,37 @@ # well with our approach. # # Currently, we only support controls on SearchResult. +# +# http://tools.ietf.org/html/rfc4511#section-4.1.1 +# http://tools.ietf.org/html/rfc4511#section-4.1.9 class Net::LDAP::PDU class Error < RuntimeError; end - ## - # This message packet is a bind request. + # http://tools.ietf.org/html/rfc4511#section-4.2 BindRequest = 0 + # http://tools.ietf.org/html/rfc4511#section-4.2.2 BindResult = 1 + # http://tools.ietf.org/html/rfc4511#section-4.3 UnbindRequest = 2 + # http://tools.ietf.org/html/rfc4511#section-4.5.1 SearchRequest = 3 + # http://tools.ietf.org/html/rfc4511#section-4.5.2 SearchReturnedData = 4 SearchResult = 5 + SearchResultReferral = 19 + # http://tools.ietf.org/html/rfc4511#section-4.6 + ModifyRequest = 6 ModifyResponse = 7 + # http://tools.ietf.org/html/rfc4511#section-4.7 + AddRequest = 8 AddResponse = 9 + # http://tools.ietf.org/html/rfc4511#section-4.8 + DeleteRequest = 10 DeleteResponse = 11 + # http://tools.ietf.org/html/rfc4511#section-4.9 + ModifyRDNRequest = 12 ModifyRDNResponse = 13 - SearchResultReferral = 19 + # http://tools.ietf.org/html/rfc4511#section-4.12 ExtendedRequest = 23 ExtendedResponse = 24 From 91cac8a9dc5a2bbee0a113818e21ce08e2a15790 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:50:25 -0700 Subject: [PATCH 248/435] Add missing app IDs based on spec --- lib/net/ldap/pdu.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index f2cd304c..f749f669 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -35,7 +35,7 @@ class Error < RuntimeError; end # http://tools.ietf.org/html/rfc4511#section-4.5.2 SearchReturnedData = 4 SearchResult = 5 - SearchResultReferral = 19 + # see also SearchResultReferral (19) # http://tools.ietf.org/html/rfc4511#section-4.6 ModifyRequest = 6 ModifyResponse = 7 @@ -48,9 +48,18 @@ class Error < RuntimeError; end # http://tools.ietf.org/html/rfc4511#section-4.9 ModifyRDNRequest = 12 ModifyRDNResponse = 13 + # http://tools.ietf.org/html/rfc4511#section-4.10 + CompareRequest = 14 + CompareResponse = 15 + # http://tools.ietf.org/html/rfc4511#section-4.11 + AbandonRequest = 16 + # http://tools.ietf.org/html/rfc4511#section-4.5.2 + SearchResultReferral = 19 # http://tools.ietf.org/html/rfc4511#section-4.12 ExtendedRequest = 23 ExtendedResponse = 24 + # unused: http://tools.ietf.org/html/rfc4511#section-4.13 + IntermediateResponse = 25 ## # The LDAP packet message ID. From b225088ee2a30d0682862954de1a910ff46b6157 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:55:16 -0700 Subject: [PATCH 249/435] Replace hardcoded application specific tags with constants --- lib/net/ldap/connection.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4efe14d8..cc74a170 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -227,7 +227,7 @@ 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(0) + psw.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::BindRequest) write(request) pdu = read @@ -265,7 +265,7 @@ def bind_sasl(auth) n = 0 loop { sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) - request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0) + request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(Net::LDAP::PDU::BindRequest) write(request) pdu = read @@ -450,7 +450,7 @@ def search(args = nil) attrs_only.to_ber, filter.to_ber, ber_attrs.to_ber_sequence - ].to_ber_appsequence(3) + ].to_ber_appsequence(Net::LDAP::PDU::SearchRequest) # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory # this breaks when calling to_ber. (Can't force binary data to UTF-8) @@ -584,7 +584,7 @@ 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(6) + ops.to_ber_sequence ].to_ber_appsequence(Net::LDAP::PDU::ModifyRequest) write(request) pdu = read @@ -610,7 +610,7 @@ 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) + request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(Net::LDAP::PDU::AddRequest) write(request) pdu = read @@ -634,7 +634,7 @@ def rename(args) 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(12)) + write(request.to_ber_appsequence(Net::LDAP::PDU::ModifyRDNRequest)) pdu = read @@ -651,7 +651,7 @@ 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(10) + request = dn.to_s.to_ber_application_string(Net::LDAP::PDU::DeleteRequest) write(request, controls) pdu = read From 7baeda36ad4fc96ee71255cd5a78218c1fe0498e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 09:26:38 -0700 Subject: [PATCH 250/435] remove skip fixed by #140 --- test/integration/test_search.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 27793c63..86494184 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -44,8 +44,6 @@ def test_search_constrained_attributes # http://tools.ietf.org/html/rfc4511#section-4.5.1.4 def test_search_size - skip "search treats sizeLimitExceeded response as failure" - entries = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) assert_equal 2, entries.size From a748ddf6e7f960c23b2473e321d570d647e3fb77 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 09:28:44 -0700 Subject: [PATCH 251/435] consolidate search size tests --- test/integration/test_search.rb | 35 +-------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 86494184..9e78a71b 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -42,40 +42,6 @@ def test_search_constrained_attributes assert_empty entry[:mail] end - # http://tools.ietf.org/html/rfc4511#section-4.5.1.4 - def test_search_size - entries = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) - - assert_equal 2, entries.size - end - - # See: test_search_size for what *should* work. - # - # This tests the currently broken behavior where searches are reported as - # failed when the size limit has been reached. This is broken since the - # sizeLimit parameter defines how many results to send back, and will result - # in a sizeLimitExceeded result in cases where there are more results than - # returned; not an error case, but also not a result code that is categorized - # as a non-error result (http://tools.ietf.org/html/rfc4511#appendix-A.1). - # The practical choice is to treat sizeLimitExceeded (and timeLimitExceeded) - # as successful search terminating messages. - def test_search_size_broken - entries = [] - - returned = @ldap.search(base: "ou=People,dc=rubyldap,dc=com", size: 2) do |entry| - entries << entry.dn - end - refute returned - - # reported as an "error" of sizeLimitExceeded - result = @ldap.get_operation_result - assert_equal 4, result.code - assert_equal Net::LDAP::ResultStrings[4], result.message - - # received the right number of results - assert_equal 2, entries.size - end - def test_search_attributes_only entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes_only: true).first @@ -96,6 +62,7 @@ def test_search_timeout assert_equal entries, result end + # http://tools.ietf.org/html/rfc4511#section-4.5.1.4 def test_search_with_size entries = [] From 55845c23ed71d66eb17e2a038ddada3441921a35 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 09:29:29 -0700 Subject: [PATCH 252/435] previous test was filtering to one user this updates it to test the size parameter works cc @mtodd @randx --- test/integration/test_search.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 9e78a71b..b56052ce 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -66,12 +66,12 @@ def test_search_timeout def test_search_with_size entries = [] - result = @ldap.search(filter: "(uid=user1)", base: "dc=rubyldap,dc=com", size: 1) do |entry| + result = @ldap.search(base: "dc=rubyldap,dc=com", size: 1) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end - refute entries.empty? + assert_equal 1, result.size assert_equal entries, result end end From 153879aacb02bfe29f85409dc80104a5f48b11d7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 10:30:15 -0700 Subject: [PATCH 253/435] require ruby >= 1.9.3 --- net-ldap.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 454ab446..b6649c03 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -29,7 +29,7 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] - s.required_ruby_version = Gem::Requirement.new(">= 1.8.7") + s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") s.rubyforge_project = %q{net-ldap} s.rubygems_version = %q{1.5.2} s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} From cc32757fa5b2c9183b19200f002be62a88144afa Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 10:30:32 -0700 Subject: [PATCH 254/435] rubyforge is no more --- net-ldap.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index b6649c03..981c75da 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -30,7 +30,6 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") - s.rubyforge_project = %q{net-ldap} s.rubygems_version = %q{1.5.2} s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} s.test_files = ["test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb"] From a4f15c85da3e3dd64b8ceb5cabd88d0e6898da67 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 22 Oct 2014 10:31:28 -0700 Subject: [PATCH 255/435] remove duplidate test_files definition --- net-ldap.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 981c75da..30ca60ad 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -32,7 +32,6 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") s.rubygems_version = %q{1.5.2} s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} - s.test_files = ["test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb"] if s.respond_to? :specification_version then s.specification_version = 3 From c00105eb8e47e7f04893bb416992fc99fc4883ff Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 01:17:59 -0700 Subject: [PATCH 256/435] 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 257/435] 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 258/435] 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 259/435] 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 260/435] 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 261/435] 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 262/435] 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 263/435] 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 From 41b22f4b637653daa93a1998a07bf83f97cac6e3 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 11:01:35 -0700 Subject: [PATCH 264/435] remove rubygems_version this will be set by the actual version that builds it http://guides.rubygems.org/specification-reference/#rubygemsversion --- net-ldap.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 30ca60ad..631d83e1 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -30,7 +30,6 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") - s.rubygems_version = %q{1.5.2} s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} if s.respond_to? :specification_version then From c6243060edeeaf069d729fd49840b1088ecb19c6 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 11:03:23 -0700 Subject: [PATCH 265/435] requirement does not actually limit anything --- net-ldap.gemspec | 2 -- 1 file changed, 2 deletions(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 631d83e1..7fd6931e 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -7,8 +7,6 @@ Gem::Specification.new do |s| s.name = %q{net-ldap} s.version = Net::LDAP::VERSION s.license = "MIT" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler", "Michael Schaarschmidt"] s.date = %q{2012-02-28} s.description = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the From be86fe97601d102f6a4828b6e75ec32d716d3a41 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 11:05:50 -0700 Subject: [PATCH 266/435] use a string for required_ruby_version See http://guides.rubygems.org/specification-reference/#required_ruby_version --- net-ldap.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 7fd6931e..2c673da7 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -27,7 +27,7 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] - s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") + s.required_ruby_version = ">= 1.9.3" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} if s.respond_to? :specification_version then From 9526493203abe9d678333ac8641e84c00948ca0c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 11:09:17 -0700 Subject: [PATCH 267/435] simplify how development dependencies are declared follows the spec reference defined in http://guides.rubygems.org/specification-reference/ --- net-ldap.gemspec | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 2c673da7..c7ce3b2a 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -30,24 +30,8 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.required_ruby_version = ">= 1.9.3" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} - if s.respond_to? :specification_version then - s.specification_version = 3 - - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q, ["~> 1"]) - s.add_development_dependency(%q, ["~> 1"]) - s.add_development_dependency(%q, [">= 1.3.0"]) - s.add_development_dependency(%q, [">= 2.9.1"]) - else - s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, [">= 1.3.0"]) - s.add_dependency(%q, [">= 2.9.1"]) - end - else - s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, ["~> 1"]) - s.add_dependency(%q, [">= 1.3.0"]) - s.add_dependency(%q, [">= 2.9.1"]) - end + s.add_development_dependency("hoe-git", "~> 1") + s.add_development_dependency("hoe-gemspec", "~> 1") + s.add_development_dependency("flexmock", ">= 1.3.0") + s.add_development_dependency("hoe", ">= 2.9.1") end From 2091729f3a96626fd37264dd5f35468a2f9ebfce Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 13:54:10 -0700 Subject: [PATCH 268/435] add contributing guide --- CONTRIBUTING.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..58889a42 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,54 @@ +# Contribution guide + +Thank you for using net-ldap. If you'd like to help, keep these guidelines in +mind. + +## Submitting a New Issue + +If you find a bug, or would like to propose an idea, file a [new issue][issues]. +Include as many details as possible: + +- Ruby and Rubygem version +- LDAP server version +- Queries, connection information, any other input +- output or error messages + +## Sending a Pull Request + +[Pull requests][pr] are always welcome! + +Check out [the project's issues list][issues] for ideas on what could be improved. + +Before sending, please add tests and ensure the test suite passes. + +To run the full suite: + + `bundle exec rake` + +To run a specific test file: + + `bundle exec ruby test/test_ldap.rb` + +To run a specific test: + + `bundle exec ruby test/test_ldap.rb -n test_instrument_bind` + +Pull requests will trigger automatic continuous integration builds on +[TravisCI][travis]. To run integration tests locally, see the `test/support` +folder. + +## Styleguide + +```ruby +# 1.9+ style hashes +{key: "value"} + +# Multi-line arguments with `\` +MyClass.new \ + foo: 'bar', + baz: 'garply' +``` + +[issues]: https://github.com/jch/html-pipeline/issues +[pr]: https://help.github.com/articles/using-pull-requests +[travis]: https://travis-ci.org/ruby-ldap/ruby-net-ldap/ From bee19aee241f69a8e0172d819364641ac0d5939c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 14:05:46 -0700 Subject: [PATCH 269/435] propose new release process --- README.rdoc | 8 ++++++++ script/package | 7 +++++++ script/release | 16 ++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100755 script/package create mode 100755 script/release diff --git a/README.rdoc b/README.rdoc index 969a717a..0a1ebdf5 100644 --- a/README.rdoc +++ b/README.rdoc @@ -37,6 +37,14 @@ sources. Simply require either 'net-ldap' or 'net/ldap'. +== Release + +This section is for gem maintainers to cut a new version of the gem. + +* Update lib/html/pipeline/version.rb to next version number X.X.X following {semver}(http://semver.org/). +* Update CHANGELOG.md. Get latest changes with `git log --oneline vLAST_RELEASE..HEAD | grep Merge` +* On the master branch, run `script/release` + :include: Contributors.rdoc :include: License.rdoc diff --git a/script/package b/script/package new file mode 100755 index 00000000..5851400e --- /dev/null +++ b/script/package @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Usage: script/package +# Updates the gemspec and builds a new gem in the pkg directory. + +mkdir -p pkg +gem build *.gemspec +mv *.gem pkg diff --git a/script/release b/script/release new file mode 100755 index 00000000..6dcd8cb3 --- /dev/null +++ b/script/release @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Usage: script/release +# Build the package, tag a commit, push it to origin, and then release the +# package publicly. + +set -e + +version="$(script/package | grep Version: | awk '{print $2}')" +[ -n "$version" ] || exit 1 + +echo $version +git commit --allow-empty -a -m "Release $version" +git tag "v$version" +git push origin +git push origin "v$version" +gem push pkg/*-${version}.gem From f658a86649e32f4336a4614ea1baa85d311ee046 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 24 Oct 2014 15:02:42 -0700 Subject: [PATCH 270/435] Add BER integration test for true value --- test/integration/test_ber.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/integration/test_ber.rb diff --git a/test/integration/test_ber.rb b/test/integration/test_ber.rb new file mode 100644 index 00000000..8fb4d374 --- /dev/null +++ b/test/integration/test_ber.rb @@ -0,0 +1,30 @@ +require_relative '../test_helper' + +class TestBERIntegration < LDAPIntegrationTestCase + # Test whether the TRUE boolean value is encoded correctly by performing a + # search operation. + def test_true_ber_encoding + # request these attrs to simplify test; use symbols to match Entry#attribute_names + attrs = [:dn, :uid, :cn, :mail] + + assert types_entry = @ldap.search( + base: "dc=rubyldap,dc=com", + filter: "(uid=user1)", + size: 1, + attributes: attrs, + attributes_only: true + ).first + + # matches attributes we requested + assert_equal attrs, types_entry.attribute_names + + # assert values are empty + types_entry.each do |name, values| + next if name == :dn + assert values.empty? + end + + assert_includes Net::LDAP::ResultCodesSearchSuccess, + @ldap.get_operation_result.code, "should be a successful search operation" + end +end From 9cd7d397b258b0429d67930b0b9a5f8e07b2d969 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 24 Oct 2014 16:22:57 -0700 Subject: [PATCH 271/435] changes for 0.9.0 --- History.rdoc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/History.rdoc b/History.rdoc index e0ee3e0a..21c50e91 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,34 @@ +=== Net::LDAP 0.9.0 +* Major changes: + * Dropped support for ruby 1.8.7 +* Major enhancements: + * Search timeout + * Instrumentation +* Bug fixes: + * Searches on the same open connection do not interleave results + * Fix search size option + * Fix BER true encoding + +* Details + * #142 Encode true as xFF + * #124, #145, #146 Cleanup gemspec + * #138, #144 Track response messages by message id + * #141 Magic number/constant cleanup + * #119, #129, #130, #132, #133, #137 Integration tests + * #115 Search timeout support + * #140 Fix search size option + * #139 Cleanup and inline documentation for Net::LDAP::Connection#search + * #131 Instrumentation + * #116 Refactor Connection#write + * #126 Update gitignore + * #128 Fix whitespace + * #113, #121 Switch to minitest + * #123 Base64 encoded dn + * #114 Separate file for Net::LDAP::Connection + * #104 Parse version spec in LDIF datasets + * #106 ldap.modify doc fixes + * #111 Fix test deprecations + === Net::LDAP 0.5.0 / 2013-07-22 * Major changes: * Required Ruby version is >=1.9.3 From 78c3c423f8c5eff6e27f9062856ea222f2e4bb21 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 10:19:53 -0700 Subject: [PATCH 272/435] fix urls --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 58889a42..11495f03 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,6 +49,6 @@ MyClass.new \ baz: 'garply' ``` -[issues]: https://github.com/jch/html-pipeline/issues +[issues]: https://github.com/ruby-net-ldap/ruby-net-ldap/issues [pr]: https://help.github.com/articles/using-pull-requests -[travis]: https://travis-ci.org/ruby-ldap/ruby-net-ldap/ +[travis]: https://travis-ci.org/ruby-ldap/ruby-net-ldap From b5fad1671fa8b6ff92e60b39694039d128841f0b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 10:20:49 -0700 Subject: [PATCH 273/435] clarify gem version --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11495f03..0247a3d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ mind. If you find a bug, or would like to propose an idea, file a [new issue][issues]. Include as many details as possible: -- Ruby and Rubygem version +- Version of net-ldap gem - LDAP server version - Queries, connection information, any other input - output or error messages From f94ecc23c9120728baf896692b8ba44fb20e0445 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 10:25:18 -0700 Subject: [PATCH 274/435] make bug fixes language consistent --- History.rdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/History.rdoc b/History.rdoc index 21c50e91..95f6f828 100644 --- a/History.rdoc +++ b/History.rdoc @@ -5,9 +5,9 @@ * Search timeout * Instrumentation * Bug fixes: - * Searches on the same open connection do not interleave results + * Fix reads for multiple concurrent requests with shared, open connections mixing up the results * Fix search size option - * Fix BER true encoding + * Fix BER encoding bug * Details * #142 Encode true as xFF From 9e1af51ade3c371db7b15117d7a977fb563d67aa Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 10:28:14 -0700 Subject: [PATCH 275/435] add clean-up section --- History.rdoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/History.rdoc b/History.rdoc index 95f6f828..e5823020 100644 --- a/History.rdoc +++ b/History.rdoc @@ -8,6 +8,9 @@ * Fix reads for multiple concurrent requests with shared, open connections mixing up the results * Fix search size option * Fix BER encoding bug +* Code clean-up: + * Added integration test suite + * Switch to minitest * Details * #142 Encode true as xFF From 96170f3c392c499c3685fc678051a2e41ad3f85d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 10:30:16 -0700 Subject: [PATCH 276/435] specify >= 1.9.3 required --- History.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index e5823020..431d9233 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,6 +1,6 @@ === Net::LDAP 0.9.0 * Major changes: - * Dropped support for ruby 1.8.7 + * Dropped support for ruby 1.8.7, ruby >= 1.9.3 now required * Major enhancements: * Search timeout * Instrumentation From bb18fc67aabedf4fec90b23e70f67d5856cef794 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:29:08 -0700 Subject: [PATCH 277/435] alpa sort capability attributes list --- lib/net/ldap.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index ac07d901..453f70c0 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1194,9 +1194,15 @@ def delete_tree(args) def search_root_dse rs = search(:ignore_server_caps => true, :base => "", :scope => SearchScope_BaseObject, - :attributes => [ :namingContexts, :supportedLdapVersion, - :altServer, :supportedControl, :supportedExtension, - :supportedFeatures, :supportedSASLMechanisms]) + :attributes => [ + :altServer, + :namingContexts, + :supportedControl, + :supportedExtension, + :supportedFeatures, + :supportedLdapVersion, + :supportedSASLMechanisms + ]) (rs and rs.first) or Net::LDAP::Entry.new end From 0c44785e5156f5ca7cd5aaca3d9e0540dc6e3f99 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:29:38 -0700 Subject: [PATCH 278/435] add activedirectory supportedCapabilities --- lib/net/ldap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 453f70c0..87c7eccb 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1197,6 +1197,7 @@ def search_root_dse :attributes => [ :altServer, :namingContexts, + :supportedCapabilities, :supportedControl, :supportedExtension, :supportedFeatures, From bcd03d0ebfe7f85110c494bea9ac99ec0eaa67a8 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:44:00 -0700 Subject: [PATCH 279/435] tweak wording --- History.rdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/History.rdoc b/History.rdoc index 431d9233..a1aa3a11 100644 --- a/History.rdoc +++ b/History.rdoc @@ -2,8 +2,8 @@ * Major changes: * Dropped support for ruby 1.8.7, ruby >= 1.9.3 now required * Major enhancements: - * Search timeout - * Instrumentation + * Add support for search time limit parameter + * Instrument received messages, PDU parsing * Bug fixes: * Fix reads for multiple concurrent requests with shared, open connections mixing up the results * Fix search size option From b72ca0f2db7a061db501f147615ff171f1949ef1 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:45:51 -0700 Subject: [PATCH 280/435] add AD capabilities querying to history --- History.rdoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/History.rdoc b/History.rdoc index a1aa3a11..170a0cea 100644 --- a/History.rdoc +++ b/History.rdoc @@ -4,6 +4,8 @@ * Major enhancements: * Add support for search time limit parameter * Instrument received messages, PDU parsing +* Minor enhancments: + * Add support for querying ActiveDirectory capabilities from root dse * Bug fixes: * Fix reads for multiple concurrent requests with shared, open connections mixing up the results * Fix search size option @@ -13,6 +15,7 @@ * Switch to minitest * Details + * #150 Support querying ActiveDirectory capabilities when searching root dse * #142 Encode true as xFF * #124, #145, #146 Cleanup gemspec * #138, #144 Track response messages by message id From 35c80564de341c125ccb1b8c1354074e75541aff Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:51:01 -0700 Subject: [PATCH 281/435] make dev dependencies not open ended silences gemspec warnings --- net-ldap.gemspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index c7ce3b2a..83478d70 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -30,8 +30,8 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.required_ruby_version = ">= 1.9.3" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} - s.add_development_dependency("hoe-git", "~> 1") - s.add_development_dependency("hoe-gemspec", "~> 1") - s.add_development_dependency("flexmock", ">= 1.3.0") - s.add_development_dependency("hoe", ">= 2.9.1") + s.add_development_dependency("hoe-git", "~> 1.0") + s.add_development_dependency("hoe-gemspec", "~> 1.0") + s.add_development_dependency("flexmock", "~> 1.3") + s.add_development_dependency("hoe", "~> 2.9") end From 04393666dc55209d1d1de22102c2013a4256618e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:53:28 -0700 Subject: [PATCH 282/435] bump version and update history --- History.rdoc | 2 +- lib/net/ldap/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.rdoc b/History.rdoc index 170a0cea..8fb39531 100644 --- a/History.rdoc +++ b/History.rdoc @@ -17,7 +17,7 @@ * Details * #150 Support querying ActiveDirectory capabilities when searching root dse * #142 Encode true as xFF - * #124, #145, #146 Cleanup gemspec + * #124, #145, #146, #152 Cleanup gemspec * #138, #144 Track response messages by message id * #141 Magic number/constant cleanup * #119, #129, #130, #132, #133, #137 Integration tests diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 155ca49c..eb2afd4a 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.8.0" + VERSION = "0.9.0" end end From e37ce91b6e4422bce3fd1092119ebe42a3c986ec Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 27 Oct 2014 16:54:54 -0700 Subject: [PATCH 283/435] Release 0.9.0 From 33f3aa0647207d52710885d38284a990b042a3e4 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:09:30 -0700 Subject: [PATCH 284/435] remove gemspec date --- net-ldap.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 83478d70..fc8baac7 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -8,7 +8,6 @@ Gem::Specification.new do |s| s.version = Net::LDAP::VERSION s.license = "MIT" s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler", "Michael Schaarschmidt"] - s.date = %q{2012-02-28} s.description = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services. Net::LDAP is written completely in From aaa4f5244ed0499d97dbcd688841a1d7f6cceef4 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:20:17 -0700 Subject: [PATCH 285/435] remove hoe --- Rakefile | 71 ++---------------------------------------------- net-ldap.gemspec | 3 -- 2 files changed, 2 insertions(+), 72 deletions(-) diff --git a/Rakefile b/Rakefile index 4db3f047..b6ed571a 100644 --- a/Rakefile +++ b/Rakefile @@ -1,74 +1,7 @@ # -*- ruby encoding: utf-8 -*- +# vim: syntax=ruby -require "rubygems" -require 'hoe' - -Hoe.plugin :doofus -Hoe.plugin :git -Hoe.plugin :gemspec - -Hoe.spec 'net-ldap' do |spec| - # spec.rubyforge_name = spec.name - - spec.developer("Francis Cianfrocca", "blackhedd@rubyforge.org") - spec.developer("Emiel van de Laar", "gemiel@gmail.com") - spec.developer("Rory O'Connell", "rory.ocon@gmail.com") - spec.developer("Kaspar Schiess", "kaspar.schiess@absurd.li") - spec.developer("Austin Ziegler", "austin@rubyforge.org") - spec.developer("Michael Schaarschmidt", "michael@schaaryworks.com") - - spec.remote_rdoc_dir = '' - spec.rsync_args << ' --exclude=statsvn/' - - spec.urls = %w(http://rubyldap.com/' 'https://github.com/ruby-ldap/ruby-net-ldap) - spec.licenses = ['MIT'] - - spec.history_file = 'History.rdoc' - spec.readme_file = 'README.rdoc' - - spec.extra_rdoc_files = FileList["*.rdoc"].to_a - - spec.extra_dev_deps << [ "hoe-git", "~> 1" ] - spec.extra_dev_deps << [ "hoe-gemspec", "~> 1" ] - spec.extra_dev_deps << [ "flexmock", ">= 1.3.0" ] - - spec.clean_globs << "coverage" - - spec.spec_extras[:required_ruby_version] = ">= 1.8.7" - spec.multiruby_skip << "1.8.6" - spec.multiruby_skip << "1_8_6" - - spec.need_tar = true -end - -# I'm not quite ready to get rid of this, but I think "rake git:manifest" is -# sufficient. -namespace :old do - desc "Build the manifest file from the current set of files." - task :build_manifest do |t| - require 'find' - - paths = [] - Find.find(".") do |path| - next if File.directory?(path) - next if path =~ /\.svn/ - next if path =~ /\.git/ - next if path =~ /\.hoerc/ - next if path =~ /\.swp$/ - next if path =~ %r{coverage/} - next if path =~ /~$/ - paths << path.sub(%r{^\./}, '') - end - - File.open("Manifest.txt", "w") do |f| - f.puts paths.sort.join("\n") - end - puts paths.sort.join("\n") - end end -desc "Run a full set of integration and unit tests" -task :cruise => [:test, :spec] - -# vim: syntax=ruby +task :default => :test diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 83478d70..3f5d1a28 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -30,8 +30,5 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.required_ruby_version = ">= 1.9.3" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} - s.add_development_dependency("hoe-git", "~> 1.0") - s.add_development_dependency("hoe-gemspec", "~> 1.0") s.add_development_dependency("flexmock", "~> 1.3") - s.add_development_dependency("hoe", "~> 2.9") end From f6b3f9c07975b0b3ea77b1371f874698a385d33a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:20:27 -0700 Subject: [PATCH 286/435] add rake --- Rakefile | 6 ++++++ net-ldap.gemspec | 1 + 2 files changed, 7 insertions(+) diff --git a/Rakefile b/Rakefile index b6ed571a..edc8fc75 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,13 @@ +#!/usr/bin/env rake # -*- ruby encoding: utf-8 -*- # vim: syntax=ruby +require 'rake/testtask' +Rake::TestTask.new do |t| + t.libs << "test" + t.test_files = FileList['test/**/test_*.rb'] + t.verbose = true end task :default => :test diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 3f5d1a28..171c2fbe 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -31,4 +31,5 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} s.add_development_dependency("flexmock", "~> 1.3") + s.add_development_dependency("rake", "~> 10.0") end From 573e0163355387708a19b9d862eba3ff6d4f29a9 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:21:34 -0700 Subject: [PATCH 287/435] remove unused manifest. generated now --- Manifest.txt | 52 ------------------------------------------------ net-ldap.gemspec | 2 +- 2 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 Manifest.txt diff --git a/Manifest.txt b/Manifest.txt deleted file mode 100644 index d1cca690..00000000 --- a/Manifest.txt +++ /dev/null @@ -1,52 +0,0 @@ -.travis.yml -Contributors.rdoc -Gemfile -Hacking.rdoc -History.rdoc -License.rdoc -Manifest.txt -README.rdoc -Rakefile -lib/net-ldap.rb -lib/net/ber.rb -lib/net/ber/ber_parser.rb -lib/net/ber/core_ext.rb -lib/net/ber/core_ext/array.rb -lib/net/ber/core_ext/bignum.rb -lib/net/ber/core_ext/false_class.rb -lib/net/ber/core_ext/fixnum.rb -lib/net/ber/core_ext/string.rb -lib/net/ber/core_ext/true_class.rb -lib/net/ldap.rb -lib/net/ldap/dataset.rb -lib/net/ldap/dn.rb -lib/net/ldap/entry.rb -lib/net/ldap/filter.rb -lib/net/ldap/instrumentation.rb -lib/net/ldap/password.rb -lib/net/ldap/pdu.rb -lib/net/ldap/version.rb -lib/net/snmp.rb -net-ldap.gemspec -spec/integration/ssl_ber_spec.rb -spec/spec_helper.rb -spec/unit/ber/ber_spec.rb -spec/unit/ber/core_ext/array_spec.rb -spec/unit/ber/core_ext/string_spec.rb -spec/unit/ldap/dn_spec.rb -spec/unit/ldap/entry_spec.rb -spec/unit/ldap/filter_parser_spec.rb -spec/unit/ldap/filter_spec.rb -spec/unit/ldap/search_spec.rb -spec/unit/ldap_spec.rb -test/common.rb -test/test_entry.rb -test/test_filter.rb -test/test_ldap_connection.rb -test/test_ldif.rb -test/test_password.rb -test/test_rename.rb -test/test_snmp.rb -test/testdata.ldif -testserver/ldapserver.rb -testserver/testdata.ldif diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 171c2fbe..30265064 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -21,7 +21,7 @@ earlier versions of the IETF LDAP RFCs (2251-2256, 2829-2830, 3377, and 3771). Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] - s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] + s.extra_rdoc_files = ["Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] s.files = `git ls-files`.split $/ s.test_files = s.files.grep(%r{^test}) s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} From e9a1b91041bc30566a90c147ca43622ad2e436e5 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:21:50 -0700 Subject: [PATCH 288/435] ignore local bundler options --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index cedadc26..9c2842d9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ pkg/ doc/ publish/ Gemfile.lock +.bundle +bin/ From 8359578b5d6436cb5e1fc826885b051bfe1297ea Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 31 Oct 2014 13:23:33 -0700 Subject: [PATCH 289/435] remove hoe references from Hacking.rdoc --- Hacking.rdoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/Hacking.rdoc b/Hacking.rdoc index 56bf73f7..4bbf4ec5 100644 --- a/Hacking.rdoc +++ b/Hacking.rdoc @@ -55,8 +55,6 @@ us with a sample LDIF data file for importing into LDAP servers for testing. Net::LDAP uses several libraries during development, all of which can be installed using RubyGems. -* *hoe* -* *hoe-git* * *flexmock* == Participation From 9b1f205f047b3429fcbc8d15254b0995e8187cef Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Wed, 12 Nov 2014 15:56:24 +0100 Subject: [PATCH 290/435] Fix test_unresponsive_host --- lib/net/ldap/connection.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 91fb7e90..508e37ac 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -17,6 +17,8 @@ def initialize(server) raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." rescue Errno::EHOSTUNREACH => error raise Net::LDAP::LdapError, "Host #{server[:host]} was unreachable (#{error.message})" + rescue Errno::ETIMEDOUT + raise Net::LDAP::LdapError, "Connection to #{server[:host]} timed out." end if server[:encryption] From d7d2c5234fba8583b005cca58f77e1929b0b7efb Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Tue, 11 Nov 2014 21:19:50 +0100 Subject: [PATCH 291/435] Implement custom tls options This allows users of the API to either specify a simple CA-File for certificate verification, or a custom SSLContext in order for a more fine-grained control of the TLS options they want to use. As of now, no additional tests were added, but the existing tests were changed to reflect the changes in internal methods, so that they can still pass --- lib/net/ldap.rb | 15 +++++++++++---- lib/net/ldap/connection.rb | 19 +++++++++++++++---- test/test_ldap_connection.rb | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 87c7eccb..fb24383e 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -537,10 +537,6 @@ def authenticate(username, password) # additional capabilities are added, more configuration values will be # added here. # - # Currently, the only supported argument is { :method => :simple_tls }. - # (Equivalently, you may pass the symbol :simple_tls all by itself, - # without enclosing it in a Hash.) - # # The :simple_tls encryption method encrypts all communications # with the LDAP server. It completely establishes SSL/TLS encryption with # the LDAP server before any LDAP-protocol data is exchanged. There is no @@ -563,6 +559,17 @@ def authenticate(username, password) # The :start_tls like the :simple_tls encryption method also encrypts all # communcations with the LDAP server. With the exception that it operates # over the standard TCP port. + # + # In order to allow verification of server certificates and other TLS-related + # options, the keys :cafile and :ssl_context can be used. + # + # The :cafile option is a single filename that points to one or more + # PEM-encoded certificates. These certificates are used as a certificate auhority + # to verify the server certificates. + # + # For fine-grained control of the TLS settings, it is also possible to use the + # :ssl_context option to pass a custom OpenSSL::SSL::SSLContext. Consult the + # OpenSSL documentation for more information on the available options. def encryption(args) case args when :simple_tls, :start_tls diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 508e37ac..987d5500 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -41,9 +41,20 @@ def close end end - def self.wrap_with_ssl(io) + def self.wrap_with_ssl(io, ssl_context = nil, cafile = nil) raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL - ctx = OpenSSL::SSL::SSLContext.new + if (ssl_context && cafile) + raise Net::LDAP::LdapError, "Please specify only one of ssl_context or cafile" + end + + ctx = ssl_context ? ssl_context : OpenSSL::SSL::SSLContext.new + + # OpenSSL automatically merges the given parameters with the default parameters + # These include verification and some common workarounds + if cafile + ctx.set_params({:ca_file => cafile}) + end + conn = OpenSSL::SSL::SSLSocket.new(io, ctx) conn.connect @@ -85,7 +96,7 @@ def self.wrap_with_ssl(io) def setup_encryption(args) case args[:method] when :simple_tls - @conn = self.class.wrap_with_ssl(@conn) + @conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile]) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls @@ -102,7 +113,7 @@ def setup_encryption(args) end if pdu.result_code.zero? - @conn = self.class.wrap_with_ssl(@conn) + @conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile]) else raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 56dfe813..583a815a 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -202,7 +202,7 @@ def test_queued_read_setup_encryption_with_start_tls 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). + flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, nil, nil). and_return(mock) conn.next_msgid # simulates ongoing query From fd78782fc64ea5c1081c3185f630cc2787a8d442 Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Thu, 13 Nov 2014 16:27:45 +0100 Subject: [PATCH 292/435] Modify parameters to reflect set_params hash By default, we don't set any parameters (empty or no :tls_options). If the hash is non-empty, we pass it directly to set_params and use the resulting context for creating the TLS socket. --- lib/net/ldap.rb | 31 ++++++++++++++++++++----------- lib/net/ldap/connection.rb | 18 +++++------------- test/test_ldap_connection.rb | 2 +- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index fb24383e..b181d83d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -560,20 +560,29 @@ def authenticate(username, password) # communcations with the LDAP server. With the exception that it operates # over the standard TCP port. # - # In order to allow verification of server certificates and other TLS-related - # options, the keys :cafile and :ssl_context can be used. - # - # The :cafile option is a single filename that points to one or more - # PEM-encoded certificates. These certificates are used as a certificate auhority - # to verify the server certificates. - # - # For fine-grained control of the TLS settings, it is also possible to use the - # :ssl_context option to pass a custom OpenSSL::SSL::SSLContext. Consult the - # OpenSSL documentation for more information on the available options. + # In order to verify certificates and enable other TLS options, the + # :tls_options hash can be passed alongside :simple_tls or :start_tls. + # This hash contains any options that can be passed to + # OpenSSL::SSL::SSLContext#set_params(). The most common options passed + # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, + # which contains a path to a Certificate Authority file (PEM-encoded). + # + # Example for a default setup without custom settings: + # { + # :method => :simple_tls, + # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS + # } + # + # Example for specifying a CA-File and only allowing TLSv1.1 connections: + # + # { + # :method => :start_tls, + # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } + # } def encryption(args) case args when :simple_tls, :start_tls - args = { :method => args } + args = { :method => args, :tls_options => {} } end @encryption = args end diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 987d5500..e45e75a6 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -41,19 +41,11 @@ def close end end - def self.wrap_with_ssl(io, ssl_context = nil, cafile = nil) + def self.wrap_with_ssl(io, tls_options = {}) raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL - if (ssl_context && cafile) - raise Net::LDAP::LdapError, "Please specify only one of ssl_context or cafile" - end - - ctx = ssl_context ? ssl_context : OpenSSL::SSL::SSLContext.new - # OpenSSL automatically merges the given parameters with the default parameters - # These include verification and some common workarounds - if cafile - ctx.set_params({:ca_file => cafile}) - end + ctx = OpenSSL::SSL::SSLContext.new + ctx.set_params(tls_options) unless tls_options.empty? conn = OpenSSL::SSL::SSLSocket.new(io, ctx) conn.connect @@ -96,7 +88,7 @@ def self.wrap_with_ssl(io, ssl_context = nil, cafile = nil) def setup_encryption(args) case args[:method] when :simple_tls - @conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile]) + @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls @@ -113,7 +105,7 @@ def setup_encryption(args) end if pdu.result_code.zero? - @conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile]) + @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) else raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 583a815a..0bffb66a 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -202,7 +202,7 @@ def test_queued_read_setup_encryption_with_start_tls 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, nil, nil). + flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, nil). and_return(mock) conn.next_msgid # simulates ongoing query From acffb16a0e7de49e911a949fb1cb9eef0caaf9fd Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Tue, 18 Nov 2014 14:41:31 +0100 Subject: [PATCH 293/435] Add comment for TLS verification in 1.0 release --- lib/net/ldap/connection.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e45e75a6..6371f636 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -45,6 +45,9 @@ def self.wrap_with_ssl(io, tls_options = {}) raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new + + # By default, we do not verify certificates. For a 1.0 release, this should probably be changed at some point. + # See discussion in https://github.com/ruby-ldap/ruby-net-ldap/pull/161 ctx.set_params(tls_options) unless tls_options.empty? conn = OpenSSL::SSL::SSLSocket.new(io, ctx) From 8d9568dd5346533d265d6861c7a8ee24bb381f79 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 21 Nov 2014 15:39:35 -0800 Subject: [PATCH 294/435] failing integration test for start_tls --- test/integration/test_bind.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index afadb4c8..c322f401 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -19,4 +19,9 @@ def test_bind_anonymous_fail def test_bind_fail refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect end + + def test_bind_tls + @ldap.encryption(method: :start_tls, tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS) + assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect + end end From f6efcd3fa259eaf1d68eaaa9c253b44c44d384b2 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 21 Nov 2014 15:27:15 -0800 Subject: [PATCH 295/435] configure openldap tls --- script/install-openldap | 59 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/script/install-openldap b/script/install-openldap index 44ee0e31..c573df03 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -5,7 +5,7 @@ set -x BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" -dpkg -s slapd time ldap-utils ||\ +dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\ DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils sudo /etc/init.d/slapd stop @@ -45,3 +45,60 @@ sudo /etc/init.d/slapd start -f $SEED_PATH/seed.ldif sudo rm -rf $TMPDIR + +# SSL + +sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem" + +sudo sh -c "cat > /etc/ssl/ca.info < /etc/ssl/ldap01.info < Date: Fri, 21 Nov 2014 15:29:05 -0800 Subject: [PATCH 296/435] support ldaps:/// --- script/install-openldap | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/script/install-openldap b/script/install-openldap index c573df03..1de8eace 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -96,6 +96,13 @@ add: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ssl/private/ldap01_slapd_key.pem EOF +# LDAP over TLS/SSL (ldaps://) is deprecated in favour of StartTLS. The latter +# refers to an existing LDAP session (listening on TCP port 389) becoming +# protected by TLS/SSL whereas LDAPS, like HTTPS, is a distinct +# encrypted-from-the-start protocol that operates over TCP port 636. But we +# enable it for testing here. +sudo sed -i -e 's|^SLAPD_SERVICES="\(.*\)"|SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"|' /etc/default/slapd + sudo adduser openldap ssl-cert sudo chgrp ssl-cert /etc/ssl/private/ldap01_slapd_key.pem sudo chmod g+r /etc/ssl/private/ldap01_slapd_key.pem From cd9668a484bb0cb36aa975b4ce3ec9d2cd6b06e7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 21 Nov 2014 16:44:49 -0800 Subject: [PATCH 297/435] oops --- script/install-openldap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/install-openldap b/script/install-openldap index 1de8eace..c399dff0 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -6,7 +6,7 @@ BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\ - DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils + DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils gnutls-bin ssl-cert sudo /etc/init.d/slapd stop From 9cf169e5b14b121f8e412fd47a72488d7572780e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 24 Nov 2014 15:59:13 -0800 Subject: [PATCH 298/435] indent params cc @mtodd --- script/install-openldap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/script/install-openldap b/script/install-openldap index c399dff0..9547f0ff 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -78,11 +78,11 @@ EOF" # Create the server certificate sudo certtool --generate-certificate \ ---load-privkey /etc/ssl/private/ldap01_slapd_key.pem \ ---load-ca-certificate /etc/ssl/certs/cacert.pem \ ---load-ca-privkey /etc/ssl/private/cakey.pem \ ---template /etc/ssl/ldap01.info \ ---outfile /etc/ssl/certs/ldap01_slapd_cert.pem + --load-privkey /etc/ssl/private/ldap01_slapd_key.pem \ + --load-ca-certificate /etc/ssl/certs/cacert.pem \ + --load-ca-privkey /etc/ssl/private/cakey.pem \ + --template /etc/ssl/ldap01.info \ + --outfile /etc/ssl/certs/ldap01_slapd_cert.pem sudo ldapmodify -Y EXTERNAL -H ldapi:/// < Date: Sun, 30 Nov 2014 16:49:11 -0800 Subject: [PATCH 299/435] Skip cert verification for test cc @jch as I'm unsure if we want to go this route or make the cert verifiable instead --- test/integration/test_bind.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index c322f401..33169330 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -21,7 +21,8 @@ def test_bind_fail end def test_bind_tls - @ldap.encryption(method: :start_tls, tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS) + tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:verify_mode => OpenSSL::SSL::VERIFY_NONE) + @ldap.encryption(method: :start_tls, tls_options: tls_options) assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end end From f3d41b5e576c209844b1c339566e71b41e3ae179 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 30 Nov 2014 17:06:17 -0800 Subject: [PATCH 300/435] Cache cacert.pem for local testing, wire up override, VM-aware path --- test/fixtures/cacert.pem | 20 ++++++++++++++++++++ test/integration/test_bind.rb | 2 +- test/test_helper.rb | 12 ++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/cacert.pem diff --git a/test/fixtures/cacert.pem b/test/fixtures/cacert.pem new file mode 100644 index 00000000..f8b134e1 --- /dev/null +++ b/test/fixtures/cacert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRzCCAf+gAwIBAgIEVHpbmjANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhy +dWJ5bGRhcDAeFw0xNDExMjkyMzQ5NDZaFw0xNTExMjkyMzQ5NDZaMBMxETAPBgNV +BAMTCHJ1YnlsZGFwMIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEA4pKe +cDCNuL53fkpO/WSAS+gmMTsOs+oOK71kZlk2QT/MBz8TxC6m358qCADjnXcMVVxa +ySQbQlVKZMkIvLNciZbiLDgC5II0NbHACNa8rqenoKRjS4J9W3OhA8EmnXn/Me+8 +uMCI9tfnKNRZYdkQZlra4I+Idn+xYfl/5q5b/7ZjPS2zY/585hFEYE+5vfOZVBSU +3HMNSeuJvTehLv7dD7aQfXNM4cRgHXequkJQ/HLLFAO4AgJ+LJrFWpj7GWz3crgr +9G5px4T78wJH3NQiOsG6UBXPw8c4T+Z6GAWX2l1zs1gZsaiCVbAraqK3404lL7yp ++ThbsW3ifzgNPhmjScXBLdbEDrrAKosW7kkTOGzxiMCBmNlj2SKhcztoduAtfF1f +Fs2Jk8MRTHwO8ThD7wIDAQABo0MwQTAPBgNVHRMBAf8EBTADAQH/MA8GA1UdDwEB +/wQFAwMHBAAwHQYDVR0OBBYEFJDm67ekyFu4/Z7VcO6Vk/5pinGcMA0GCSqGSIb3 +DQEBCwUAA4IBMQDHeEPzfYRtjynpUKyrtxx/6ZVOfCLuz4eHkBZggz/pJacDCv/a +I//W03XCk8RWq/fWVVUzvxXgPwnYcw992PLM7XW81zp6ruRUDWooYnjHZZz3bRhe +kC4QvM2mZhcsMVmhmWWKZn81qXgVdUY1XNRhk87cuXjF/UTpEieFvWAsCUkFZkqB +AmySCuI/FuPaauT1YAltkIlYAEIGNJGZDMf2BTVUQpXhTXeS9/AZWLNDBwiq+fwo +YYnsr9MnBXCEmg1gVSR/Ay2AZmbYfiYtb5kU8uq2lSWAUb4LX6HZl82wo3OilrJ2 +WXl6Qf+Fcy4qqkRt4AKHjtzizpEDCOVYuuG0Zoy+QnxNXRsEzpb8ymnJFrcgYfk/ +6Lv2gWAFl5FqCZp7gBWg55eL2coT4C+mbNTF +-----END CERTIFICATE----- diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index 33169330..dd4683fc 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -21,7 +21,7 @@ def test_bind_fail end def test_bind_tls - tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:verify_mode => OpenSSL::SSL::VERIFY_NONE) + tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:ca_file => CA_FILE) @ldap.encryption(method: :start_tls, tls_options: tls_options) assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end diff --git a/test/test_helper.rb b/test/test_helper.rb index f208977d..640b0e23 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -6,6 +6,18 @@ # Whether integration tests should be run. INTEGRATION = ENV.fetch("INTEGRATION", "skip") != "skip" +# The CA file to verify certs against for tests. +# Override with CA_FILE env variable; otherwise checks for the VM-specific path +# and falls back to the test/fixtures/cacert.pem for local testing. +CA_FILE = + ENV.fetch("CA_FILE") do + if File.exist?("/etc/ssl/certs/cacert.pem") + "/etc/ssl/certs/cacert.pem" + else + File.expand_path("fixtures/cacert.pem", File.dirname(__FILE__)) + end + end + if RUBY_VERSION < "2.0" class String def b From 7a6037585775002821ee9efd8b28619f8b273f63 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Sun, 30 Nov 2014 17:27:24 -0800 Subject: [PATCH 301/435] Fix build badge URL Was pointing at the github/ruby-net-ldap fork. --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 0a1ebdf5..63291edf 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -= Net::LDAP for Ruby {}[https://travis-ci.org/github/ruby-net-ldap] += Net::LDAP for Ruby {}[https://travis-ci.org/github/ruby-net-ldap] == Description From d2862209889e6711444259a55e869d7dcb0580c3 Mon Sep 17 00:00:00 2001 From: Andre Marques Lee Date: Wed, 3 Dec 2014 00:21:28 +0000 Subject: [PATCH 302/435] Implemented a couple of bug fixes: * Connection#search now does more graceful nil-checking in its ensure clause, reducing cryptic crash messages * Filter class methods should now be able to gracefully accept numeric literals as filter rhs values --- lib/net/ldap/connection.rb | 3 ++- lib/net/ldap/filter.rb | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 91fb7e90..c690a8c3 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -562,12 +562,13 @@ def search(args = nil) result_pdu || OpenStruct.new(:status => :failure, :result_code => Net::LDAP::ResultCodeOperationsError, :message => "Invalid search") end # instrument ensure + # clean up message queue for this search messages = message_queue.delete(message_id) # in the exceptional case some messages were *not* consumed from the queue, # instrument the event but do not fail. - unless messages.empty? + unless messages.nil? or messages.empty? instrument "search_messages_unread.net_ldap_connection", message_id: message_id, messages: messages end diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 5d91f9f6..5a2528bd 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -644,10 +644,18 @@ def match(entry) end ## - # Converts escaped characters (e.g., "\\28") to unescaped characters + # If the argument is a string, converts escaped characters (e.g., "\\28") to unescaped characters. + # If the argument is a number, just return as-is. + # Otherwise, an exception is thrown and the rhs argument is rejected. # ("("). def unescape(right) - right.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") } + if defined? right.gsub + right.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") } + elsif right.is_a? Fixnum + right.to_s + else + raise ArgumentError, "Did not know how to convert argument \"#{right}\" into the rhs of an LDAP filter" + end end private :unescape From 23ee34f668304bc31967536352d691af6c03a591 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 9 Dec 2014 16:38:18 -0800 Subject: [PATCH 303/435] Add verify none test, differentiate --- test/integration/test_bind.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index dd4683fc..bea6b034 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -20,9 +20,15 @@ def test_bind_fail refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect end - def test_bind_tls + def test_bind_tls_with_cafile tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:ca_file => CA_FILE) @ldap.encryption(method: :start_tls, tls_options: tls_options) assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end + + def test_bind_tls_with_verify_none + tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:verify_mode => OpenSSL::SSL::VERIFY_NONE) + @ldap.encryption(method: :start_tls, tls_options: tls_options) + assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect + end end From d2b67dcf842d7b30758902d228c46215348d83fc Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 9 Dec 2014 16:44:31 -0800 Subject: [PATCH 304/435] Bump version to 0.10.0 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index eb2afd4a..f49c0d08 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.9.0" + VERSION = "0.10.0" end end From cfa1c03c9a0ffb6a42632a0c6f987d37ab0f90c8 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 9 Dec 2014 16:59:50 -0800 Subject: [PATCH 305/435] Add changelog to history file --- History.rdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/History.rdoc b/History.rdoc index 8fb39531..920b2f72 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,15 @@ +=== Net::LDAP 0.10.0 +* Major enhancements: + * Accept SimpleTLS/StartTLS encryption options (compatible with `OpenSSL::SSL::SSLContext#set_params`) +* Bug fixes: + * Parse filter strings with square and curly braces (`[]` and `{}`) + * Handle connection timeout errors (`Errno::ETIMEDOUT` raised as `Net::LDAP::LdapError`) +* Testing changes: + * Add integration tests for StartTLS connections to OpenLDAP +* Meta changes: + * Update Gem release tooling (remove Hoe, use Rake) + * Fix Gem release date + === Net::LDAP 0.9.0 * Major changes: * Dropped support for ruby 1.8.7, ruby >= 1.9.3 now required From 46c3250b18c91fcaab17fee9fab0d27f45c1962a Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 9 Dec 2014 17:00:41 -0800 Subject: [PATCH 306/435] Fix minor release notes in README --- README.rdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rdoc b/README.rdoc index 63291edf..e34162b8 100644 --- a/README.rdoc +++ b/README.rdoc @@ -41,8 +41,8 @@ Simply require either 'net-ldap' or 'net/ldap'. This section is for gem maintainers to cut a new version of the gem. -* Update lib/html/pipeline/version.rb to next version number X.X.X following {semver}(http://semver.org/). -* Update CHANGELOG.md. Get latest changes with `git log --oneline vLAST_RELEASE..HEAD | grep Merge` +* Update lib/net/ldap/version.rb to next version number X.X.X following {semver}(http://semver.org/). +* Update `History.rdoc`. Get latest changes with `git log --oneline vLAST_RELEASE..HEAD | grep Merge` * On the master branch, run `script/release` :include: Contributors.rdoc From 77387bfc6a27b1b3b854942d16c09f5c568509ee Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 9 Dec 2014 17:05:36 -0800 Subject: [PATCH 307/435] Release 0.10.0 From 0dfe4847b3e9183ba911a972a73eadd84e75fde0 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 11 Dec 2014 13:09:08 -0800 Subject: [PATCH 308/435] test ber encoding of message_id > 128 --- test/integration/test_ber.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/integration/test_ber.rb b/test/integration/test_ber.rb index 8fb4d374..5d5424b4 100644 --- a/test/integration/test_ber.rb +++ b/test/integration/test_ber.rb @@ -27,4 +27,18 @@ def test_true_ber_encoding assert_includes Net::LDAP::ResultCodesSearchSuccess, @ldap.get_operation_result.code, "should be a successful search operation" end + + def test_ber_encoding_message_id_greater_than_128 + @ldap.open do |client| + 256.times { + entries = client.search \ + base: "dc=rubyldap,dc=com", + filter: "(uid=user1)", + size: 1 + assert_equal "uid=user1,ou=People,dc=rubyldap,dc=com", entries.first.dn + } + message_id = client.instance_variable_get('@open_connection').instance_variable_get('@msgid') + assert_operator message_id, :>, 256 # includes non-search messages + end + end end From dbfe4a14e96ff2543820e30b2dfa8bca302427a0 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 11 Dec 2014 19:32:13 -0800 Subject: [PATCH 309/435] Fix BER encoding test fixture for int value 128 --- test/ber/test_ber.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 7eade7c2..acaf70e8 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -26,7 +26,7 @@ def test_false 0 => "\x02\x01\x00", 1 => "\x02\x01\x01", 127 => "\x02\x01\x7F", - 128 => "\x02\x01\x80", + 128 => "\x02\x02\x00\x80", 255 => "\x02\x01\xFF", 256 => "\x02\x02\x01\x00", 65535 => "\x02\x02\xFF\xFF", From dc21554e560bb9648a23b071cdbec176d58c833f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 11 Dec 2014 20:26:12 -0800 Subject: [PATCH 310/435] Try padding based on most significant bit --- lib/net/ber/core_ext/fixnum.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/net/ber/core_ext/fixnum.rb b/lib/net/ber/core_ext/fixnum.rb index 221baddf..5aa4cadc 100644 --- a/lib/net/ber/core_ext/fixnum.rb +++ b/lib/net/ber/core_ext/fixnum.rb @@ -48,6 +48,14 @@ def to_ber_internal size -= 1 end + # for positive integers, if most significant bit is set to one, + # pad the result (otherwise it's decoded as a negative value) + # See section 8.5 of ITU-T X.690: + # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + if self > 0 && (self & (0b10000000 << (size - 1))) > 0 + size += 1 + end + # Store the size of the fixnum in the result result = [size] From af677a5a55d7a2f5413816c3b9b5cc69706718c7 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 12 Dec 2014 16:46:35 -0800 Subject: [PATCH 311/435] Pad based on most significant bit in octet Was just looking at most significant bit. --- lib/net/ber/core_ext/fixnum.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ber/core_ext/fixnum.rb b/lib/net/ber/core_ext/fixnum.rb index 5aa4cadc..3af596c9 100644 --- a/lib/net/ber/core_ext/fixnum.rb +++ b/lib/net/ber/core_ext/fixnum.rb @@ -48,11 +48,11 @@ def to_ber_internal size -= 1 end - # for positive integers, if most significant bit is set to one, + # for positive integers, if most significant bit in an octet is set to one, # pad the result (otherwise it's decoded as a negative value) # See section 8.5 of ITU-T X.690: # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - if self > 0 && (self & (0b10000000 << (size - 1))) > 0 + if self > 0 && (self & (0b10000000 << (size - 1) * 8)) > 0 size += 1 end From b907513c83f23bfa3692b27e49458252aac6aa8f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 12 Dec 2014 16:47:28 -0800 Subject: [PATCH 312/435] Fix the expected encoded value for 255 --- test/ber/test_ber.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index acaf70e8..da9bd8c3 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -27,7 +27,7 @@ def test_false 1 => "\x02\x01\x01", 127 => "\x02\x01\x7F", 128 => "\x02\x02\x00\x80", - 255 => "\x02\x01\xFF", + 255 => "\x02\x02\x00\xFF", 256 => "\x02\x02\x01\x00", 65535 => "\x02\x02\xFF\xFF", 65536 => "\x02\x03\x01\x00\x00", From 7744f7fbe6f7a38afe1c1346ef088d184bacfd26 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 12 Dec 2014 16:48:52 -0800 Subject: [PATCH 313/435] Add negative reference encoded values, but disable --- test/ber/test_ber.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index da9bd8c3..b506153e 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -40,7 +40,12 @@ def test_false 5 => "\002\001\005", 500 => "\002\002\001\364", 50_000 => "\x02\x02\xC3P", - 5_000_000_000 => "\002\005\001*\005\362\000" + 5_000_000_000 => "\002\005\001*\005\362\000", + + # negatives + # -1 => "\x02\x01\xFF", + # -127 => "\x02\x01\x81", + # -128 => "\x02\x01\x80" }.each do |number, expected_encoding| define_method "test_encode_#{number}" do assert_equal expected_encoding.b, number.to_ber From 1dca2b9f4c1f7adfbcd6d78630a3a90b284bc24f Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 12 Dec 2014 17:43:16 -0800 Subject: [PATCH 314/435] Fix expected encoded integers Makes the format consistent (hex), and updated based on various sample sources. --- test/ber/test_ber.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index b506153e..f212fd1b 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -29,18 +29,20 @@ def test_false 128 => "\x02\x02\x00\x80", 255 => "\x02\x02\x00\xFF", 256 => "\x02\x02\x01\x00", - 65535 => "\x02\x02\xFF\xFF", + 65535 => "\x02\x03\x00\xFF\xFF", 65536 => "\x02\x03\x01\x00\x00", - 16_777_215 => "\x02\x03\xFF\xFF\xFF", + 8388607 => "\x02\x03\x7F\xFF\xFF", + 8388608 => "\x02\x04\x00\x80\x00\x00", + 16_777_215 => "\x02\x04\x00\xFF\xFF\xFF", 0x01000000 => "\x02\x04\x01\x00\x00\x00", 0x3FFFFFFF => "\x02\x04\x3F\xFF\xFF\xFF", 0x4FFFFFFF => "\x02\x04\x4F\xFF\xFF\xFF", # Some odd samples... - 5 => "\002\001\005", - 500 => "\002\002\001\364", - 50_000 => "\x02\x02\xC3P", - 5_000_000_000 => "\002\005\001*\005\362\000", + 5 => "\x02\x01\x05", + 500 => "\x02\x02\x01\xf4", + 50_000 => "\x02\x03\x00\xC3\x50", + 5_000_000_000 => "\x02\x05\x01\x2a\x05\xF2\x00", # negatives # -1 => "\x02\x01\xFF", From f26c961da5d9bdb978d43d4a67857fa6eb41ad6c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Fri, 12 Dec 2014 17:44:40 -0800 Subject: [PATCH 315/435] Add roundtrip encoding/decoding tests for samples --- test/ber/test_ber.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index f212fd1b..a524661c 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -52,6 +52,10 @@ def test_false define_method "test_encode_#{number}" do assert_equal expected_encoding.b, number.to_ber end + + define_method "test_decode_encoded_#{number}" do + assert_equal number, expected_encoding.b.read_ber + end end # Round-trip encoding: This is mostly to be sure to cover Bignums well. From 5e4c114d53620691d0d91ad0bb66c6a8d0b3d82d Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 15 Dec 2014 01:13:30 -0800 Subject: [PATCH 316/435] Fix negative Fixnum encoding --- lib/net/ber/core_ext/fixnum.rb | 16 ++++++++++------ test/ber/test_ber.rb | 6 +++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/net/ber/core_ext/fixnum.rb b/lib/net/ber/core_ext/fixnum.rb index 3af596c9..8bdcb2a3 100644 --- a/lib/net/ber/core_ext/fixnum.rb +++ b/lib/net/ber/core_ext/fixnum.rb @@ -42,17 +42,21 @@ def to_ber_internal # Looks for the first byte in the fixnum that is not all zeroes. It does # this by masking one byte after another, checking the result for bits # that are left on. - size = Net::BER::MAX_FIXNUM_SIZE - while size > 1 - break if (self & (0xff << (size - 1) * 8)) > 0 - size -= 1 - end + val = (self < 0) ? ~self : self + size = 1 + size += 1 until (val >> (size * 8)).zero? # for positive integers, if most significant bit in an octet is set to one, # pad the result (otherwise it's decoded as a negative value) # See section 8.5 of ITU-T X.690: # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - if self > 0 && (self & (0b10000000 << (size - 1) * 8)) > 0 + if self > 0 && (self & (0x80 << (size - 1) * 8)) > 0 + size += 1 + end + + # and for negative integers, pad if the most significant bit in the octet + # is not set to one. + if self < 0 && (self & (0x80 << (size - 1) * 8)) == 0 size += 1 end diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index a524661c..3cb5035f 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -45,9 +45,9 @@ def test_false 5_000_000_000 => "\x02\x05\x01\x2a\x05\xF2\x00", # negatives - # -1 => "\x02\x01\xFF", - # -127 => "\x02\x01\x81", - # -128 => "\x02\x01\x80" + -1 => "\x02\x01\xFF", + -127 => "\x02\x01\x81", + -128 => "\x02\x01\x80" }.each do |number, expected_encoding| define_method "test_encode_#{number}" do assert_equal expected_encoding.b, number.to_ber From 22fdce141ea6327358e7622468c319fd5cf46ca1 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 15 Dec 2014 01:14:07 -0800 Subject: [PATCH 317/435] Fix negative integer decoding --- lib/net/ber/ber_parser.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/net/ber/ber_parser.rb b/lib/net/ber/ber_parser.rb index ea6c0788..09de8c82 100644 --- a/lib/net/ber/ber_parser.rb +++ b/lib/net/ber/ber_parser.rb @@ -41,9 +41,18 @@ def parse_ber_object(syntax, id, data) s.ber_identifier = id s elsif object_type == :integer - j = 0 - data.each_byte { |b| j = (j << 8) + b } - j + neg = !(data.unpack("C").first & 0x80).zero? + int = 0 + + data.each_byte do |b| + int = (int << 8) + (neg ? 255 - b : b) + end + + if neg + (int + 1) * -1 + else + int + end elsif object_type == :oid # See X.690 pgh 8.19 for an explanation of this algorithm. # This is potentially not good enough. We may need a From c56897f9a54ab15be688be7debf975bfddb0c6a1 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 15 Dec 2014 01:14:13 -0800 Subject: [PATCH 318/435] Spelling correction --- lib/net/ber/core_ext/fixnum.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ber/core_ext/fixnum.rb b/lib/net/ber/core_ext/fixnum.rb index 8bdcb2a3..c6d4a852 100644 --- a/lib/net/ber/core_ext/fixnum.rb +++ b/lib/net/ber/core_ext/fixnum.rb @@ -15,7 +15,7 @@ def to_ber_enumerated end ## - # Converts the fixnum to BER length encodining format. + # Converts the fixnum to BER length encoding format. def to_ber_length_encoding if self <= 127 [self].pack('C') From 8d53891ed266b8355dc62a57733520b33def7ba8 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 15 Dec 2014 01:21:28 -0800 Subject: [PATCH 319/435] Consolidate Fixnum, Bignum ext into Integer --- lib/net/ber/core_ext.rb | 13 ++----- lib/net/ber/core_ext/bignum.rb | 22 ----------- .../ber/core_ext/{fixnum.rb => integer.rb} | 38 +++++++++---------- 3 files changed, 20 insertions(+), 53 deletions(-) delete mode 100644 lib/net/ber/core_ext/bignum.rb rename lib/net/ber/core_ext/{fixnum.rb => integer.rb} (58%) diff --git a/lib/net/ber/core_ext.rb b/lib/net/ber/core_ext.rb index f46acb89..b1939844 100644 --- a/lib/net/ber/core_ext.rb +++ b/lib/net/ber/core_ext.rb @@ -33,17 +33,10 @@ class Array end # :startdoc: -require 'net/ber/core_ext/bignum' +require 'net/ber/core_ext/integer' # :stopdoc: -class Bignum - include Net::BER::Extensions::Bignum -end -# :startdoc: - -require 'net/ber/core_ext/fixnum' -# :stopdoc: -class Fixnum - include Net::BER::Extensions::Fixnum +class Integer + include Net::BER::Extensions::Integer end # :startdoc: diff --git a/lib/net/ber/core_ext/bignum.rb b/lib/net/ber/core_ext/bignum.rb deleted file mode 100644 index dc62fb8b..00000000 --- a/lib/net/ber/core_ext/bignum.rb +++ /dev/null @@ -1,22 +0,0 @@ -# -*- ruby encoding: utf-8 -*- -## -# BER extensions to the Bignum class. -module Net::BER::Extensions::Bignum - ## - # Converts a Bignum to an uncompressed BER integer. - def to_ber - result = [] - - # NOTE: Array#pack's 'w' is a BER _compressed_ integer. We need - # uncompressed BER integers, so we're not using that. See also: - # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/228864 - n = self - while n > 0 - b = n & 0xff - result << b - n = n >> 8 - end - - "\002" + ([result.size] + result.reverse).pack('C*') - end -end diff --git a/lib/net/ber/core_ext/fixnum.rb b/lib/net/ber/core_ext/integer.rb similarity index 58% rename from lib/net/ber/core_ext/fixnum.rb rename to lib/net/ber/core_ext/integer.rb index c6d4a852..b2149f9b 100644 --- a/lib/net/ber/core_ext/fixnum.rb +++ b/lib/net/ber/core_ext/integer.rb @@ -1,21 +1,21 @@ # -*- ruby encoding: utf-8 -*- ## -# Ber extensions to the Fixnum class. -module Net::BER::Extensions::Fixnum +# BER extensions to the Integer class, affecting Fixnum and Bignum objects. +module Net::BER::Extensions::Integer ## - # Converts the fixnum to BER format. + # Converts the Integer to BER format. def to_ber "\002#{to_ber_internal}" end ## - # Converts the fixnum to BER enumerated format. + # Converts the Integer to BER enumerated format. def to_ber_enumerated "\012#{to_ber_internal}" end ## - # Converts the fixnum to BER length encoding format. + # Converts the Integer to BER length encoding format. def to_ber_length_encoding if self <= 127 [self].pack('C') @@ -33,38 +33,34 @@ def to_ber_application(tag) end ## - # Used to BER-encode the length and content bytes of a Fixnum. Callers + # Used to BER-encode the length and content bytes of an Integer. Callers # must prepend the tag byte for the contained value. def to_ber_internal - # CAUTION: Bit twiddling ahead. You might want to shield your eyes or - # something. - - # Looks for the first byte in the fixnum that is not all zeroes. It does - # this by masking one byte after another, checking the result for bits - # that are left on. - val = (self < 0) ? ~self : self + # Compute the byte length, accounting for negative values requiring two's + # complement. size = 1 - size += 1 until (val >> (size * 8)).zero? + size += 1 until (((self < 0) ? ~self : self) >> (size * 8)).zero? - # for positive integers, if most significant bit in an octet is set to one, - # pad the result (otherwise it's decoded as a negative value) - # See section 8.5 of ITU-T X.690: + # Padding for positive, negative values. See section 8.5 of ITU-T X.690: # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + + # For positive integers, if most significant bit in an octet is set to one, + # pad the result (otherwise it's decoded as a negative value). if self > 0 && (self & (0x80 << (size - 1) * 8)) > 0 size += 1 end - # and for negative integers, pad if the most significant bit in the octet - # is not set to one. + # And for negative integers, pad if the most significant bit in the octet + # is not set to one (othwerise, it's decoded as positive value). if self < 0 && (self & (0x80 << (size - 1) * 8)) == 0 size += 1 end - # Store the size of the fixnum in the result + # Store the size of the Integer in the result result = [size] # Appends bytes to result, starting with higher orders first. Extraction - # of bytes is done by right shifting the original fixnum by an amount + # of bytes is done by right shifting the original Integer by an amount # and then masking that with 0xff. while size > 0 # right shift size - 1 bytes, mask with 0xff From c207770599a4a7aef711a66c5fede494271db831 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Mon, 15 Dec 2014 01:42:22 -0800 Subject: [PATCH 320/435] Expand negative test samples --- test/ber/test_ber.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 3cb5035f..92b3902d 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -47,7 +47,15 @@ def test_false # negatives -1 => "\x02\x01\xFF", -127 => "\x02\x01\x81", - -128 => "\x02\x01\x80" + -128 => "\x02\x01\x80", + -255 => "\x02\x02\xFF\x01", + -256 => "\x02\x02\xFF\x00", + -65535 => "\x02\x03\xFF\x00\x01", + -65536 => "\x02\x03\xFF\x00\x00", + -65537 => "\x02\x03\xFE\xFF\xFF", + -8388607 => "\x02\x03\x80\x00\x01", + -8388608 => "\x02\x03\x80\x00\x00", + -16_777_215 => "\x02\x04\xFF\x00\x00\x01", }.each do |number, expected_encoding| define_method "test_encode_#{number}" do assert_equal expected_encoding.b, number.to_ber From 9dc136215b2278382eba50b84b85b8c7478b4131 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 15 Dec 2014 10:27:01 -0800 Subject: [PATCH 321/435] remove unused integration test --- test/integration/test_ber.rb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/integration/test_ber.rb b/test/integration/test_ber.rb index 5d5424b4..8fb4d374 100644 --- a/test/integration/test_ber.rb +++ b/test/integration/test_ber.rb @@ -27,18 +27,4 @@ def test_true_ber_encoding assert_includes Net::LDAP::ResultCodesSearchSuccess, @ldap.get_operation_result.code, "should be a successful search operation" end - - def test_ber_encoding_message_id_greater_than_128 - @ldap.open do |client| - 256.times { - entries = client.search \ - base: "dc=rubyldap,dc=com", - filter: "(uid=user1)", - size: 1 - assert_equal "uid=user1,ou=People,dc=rubyldap,dc=com", entries.first.dn - } - message_id = client.instance_variable_get('@open_connection').instance_variable_get('@msgid') - assert_operator message_id, :>, 256 # includes non-search messages - end - end end From 44054b8265fb4210038607bcffceb0d3ebc80c94 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 16 Dec 2014 13:46:10 -0800 Subject: [PATCH 322/435] Add 0.10.1 changelog notes --- History.rdoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/History.rdoc b/History.rdoc index 920b2f72..c3a786a0 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,7 @@ +=== Net::LDAP 0.10.1 +* Bug fixes: + * Fix Integer BER encoding of signed values + === Net::LDAP 0.10.0 * Major enhancements: * Accept SimpleTLS/StartTLS encryption options (compatible with `OpenSSL::SSL::SSLContext#set_params`) From a2c9bd2833bd7082f6c580b8cb5696d60a20eefe Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 16 Dec 2014 13:46:33 -0800 Subject: [PATCH 323/435] Bump version to 0.10.1 --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index f49c0d08..5ecad815 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.10.0" + VERSION = "0.10.1" end end From fd2d1ed62df1e65a50627b429bce7a49cd623b04 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Tue, 16 Dec 2014 13:56:10 -0800 Subject: [PATCH 324/435] Release 0.10.1 From e59543bb28f14083cf73ca2ee2f2a99d03560038 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 17 Dec 2014 09:43:29 -0800 Subject: [PATCH 325/435] fix nil tls_options --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 6371f636..ab7931d1 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -91,7 +91,7 @@ def self.wrap_with_ssl(io, tls_options = {}) def setup_encryption(args) case args[:method] when :simple_tls - @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) + @conn = self.class.wrap_with_ssl(@conn, args.fetch(:tls_options, {})) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls From 13ca7c9dee5bcb9e91c8f87c482f2eba885e7787 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 17 Dec 2014 09:46:31 -0800 Subject: [PATCH 326/435] encryption defaults empty :tls_options --- lib/net/ldap/connection.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index ab7931d1..0e3d7e05 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -89,9 +89,10 @@ def self.wrap_with_ssl(io, tls_options = {}) # generously contributing the :start_tls path. #++ def setup_encryption(args) + args[:tls_options] ||= {} case args[:method] when :simple_tls - @conn = self.class.wrap_with_ssl(@conn, args.fetch(:tls_options, {})) + @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls From f8987cbf2e47d0b725827e57677907088cd9d4a0 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 18 Dec 2014 15:19:51 -0800 Subject: [PATCH 327/435] update mock --- test/test_ldap_connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 0bffb66a..424f6bb3 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -202,7 +202,7 @@ def test_queued_read_setup_encryption_with_start_tls 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, nil). + flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, {}). and_return(mock) conn.next_msgid # simulates ongoing query From 443fdb1fda855031d958a587dd6a2b272edb5b16 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Wed, 17 Dec 2014 14:49:21 -0700 Subject: [PATCH 328/435] refactor connection establishment reduces duplicated code, and makes it easier for future changes to connection establishment because it's all in one place now --- Contributors.rdoc | 1 + lib/net/ldap.rb | 138 +++++++++++++++------------------------------- 2 files changed, 45 insertions(+), 94 deletions(-) diff --git a/Contributors.rdoc b/Contributors.rdoc index bef012a9..b3b25ff6 100644 --- a/Contributors.rdoc +++ b/Contributors.rdoc @@ -20,3 +20,4 @@ Contributions since: * Erik Hetzner (egh) * nowhereman * David J. Lee (DavidJLee) +* Cody Cutrer (ccutrer) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index b181d83d..d61f3dc4 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -670,12 +670,7 @@ def open instrument "open.net_ldap" do |payload| begin - @open_connection = - Net::LDAP::Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service + @open_connection = new_connection payload[:connection] = @open_connection payload[:bind] = @open_connection.bind(@auth) yield self @@ -745,27 +740,11 @@ def search(args = {}) result_set = return_result_set ? [] : nil instrument "search.net_ldap", args do |payload| - if @open_connection - @result = @open_connection.search(args) { |entry| + @result = use_connection(args) do |conn| + conn.search(args) { |entry| result_set << entry if result_set yield entry if block_given? } - else - begin - conn = Net::LDAP::Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess - @result = conn.search(args) { |entry| - result_set << entry if result_set - yield entry if block_given? - } - end - ensure - conn.close if conn - end end if return_result_set @@ -844,11 +823,7 @@ def bind(auth = @auth) payload[:bind] = @result = @open_connection.bind(auth) else begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service + conn = new_connection payload[:connection] = conn payload[:bind] = @result = conn.bind(auth) ensure @@ -946,22 +921,8 @@ def bind_as(args = {}) # end def add(args) instrument "add.net_ldap", args do |payload| - if @open_connection - @result = @open_connection.add(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess - @result = conn.add(args) - end - ensure - conn.close if conn - end + @result = use_connection(args) do |conn| + conn.add(args) end @result.success? end @@ -1050,24 +1011,9 @@ def add(args) # does _not_ imply transactional atomicity, which LDAP does not provide. def modify(args) instrument "modify.net_ldap", args do |payload| - if @open_connection - @result = @open_connection.modify(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess - @result = conn.modify(args) - end - ensure - conn.close if conn - end + @result = use_connection(args) do |conn| + conn.modify(args) end - @result.success? end end @@ -1127,22 +1073,8 @@ def delete_attribute(dn, attribute) # _Documentation_ _stub_ def rename(args) instrument "rename.net_ldap", args do |payload| - if @open_connection - @result = @open_connection.rename(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess - @result = conn.rename(args) - end - ensure - conn.close if conn - end + @result = use_connection(args) do |conn| + conn.rename(args) end @result.success? end @@ -1160,22 +1092,8 @@ def rename(args) # ldap.delete :dn => dn def delete(args) instrument "delete.net_ldap", args do |payload| - if @open_connection - @result = @open_connection.delete(args) - else - @result = 0 - begin - conn = Connection.new \ - :host => @host, - :port => @port, - :encryption => @encryption, - :instrumentation_service => @instrumentation_service - if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess - @result = conn.delete(args) - end - ensure - conn.close - end + @result = use_connection(args) do |conn| + conn.delete(args) end @result.success? end @@ -1277,4 +1195,36 @@ def paged_searches_supported? @server_caps ||= search_root_dse @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) end + + private + + # Yields an open connection if there is one, otherwise establishes a new + # connection, binds, and yields it. If binding fails, it will return the + # result from that, and :use_connection: will not yield at all. If not + # the return value is whatever is returned from the block. + def use_connection(args) + if @open_connection + yield @open_connection + else + begin + conn = new_connection + if (result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess + yield conn + else + return result + end + ensure + conn.close if conn + end + end + end + + # Establish a new connection to the LDAP server + def new_connection + Net::LDAP::Connection.new \ + :host => @host, + :port => @port, + :encryption => @encryption, + :instrumentation_service => @instrumentation_service + end end # class LDAP From a6d6ec8285f2548fa0c08169ecc65b112922c5bd Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sun, 4 Jan 2015 15:28:35 +0900 Subject: [PATCH 329/435] Rename Net::LDAP::LdapError to Net::LDAP::Error --- lib/net/ldap.rb | 30 +----------------------------- lib/net/ldap/error.rb | 31 +++++++++++++++++++++++++++++++ test/test_ldap_connection.rb | 4 ++-- 3 files changed, 34 insertions(+), 31 deletions(-) create mode 100644 lib/net/ldap/error.rb diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index fa05ea78..75b463fb 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -26,6 +26,7 @@ class LDAP require 'net/ldap/instrumentation' require 'net/ldap/connection' require 'net/ldap/version' +require 'net/ldap/error' # == Quick-start for the Impatient # === Quick Example of a user-authentication against an LDAP directory: @@ -246,35 +247,6 @@ class LDAP class Net::LDAP include Net::LDAP::Instrumentation - class LdapError < StandardError; end - class AlreadyOpenedError < LdapError; end - class SocketError < LdapError; end - class ConnectionRefusedError < LdapError; end - class NoOpenSSLError < LdapError; end - class NoStartTLSResultError < LdapError; end - class StartTLSError < LdapError; end - class EncryptionUnsupportedError < LdapError; end - class EncMethodUnsupportedError < LdapError; end - class AuthMethodUnsupportedError < LdapError; end - class BindingInformationInvalidError < LdapError; end - class NoBindResultError < LdapError; end - class SASLChallengeOverflowError < LdapError; end - class SearchSizeInvalidError < LdapError; end - class SearchScopeInvalidError < LdapError; end - class ResponseTypeInvalidError < LdapError; end - class ResponseMissingOrInvalidError < LdapError; end - class EmptyDNError < LdapError; end - class HashTypeUnsupportedError < LdapError; end - class OperatorError < LdapError; end - class SubstringFilterError < LdapError; end - class SearchFilterError < LdapError; end - class BERInvalidError < LdapError; end - class SearchFilterTypeUnknownError < LdapError; end - class BadAttributeError < LdapError; end - class FilterTypeUnknownError < LdapError; end - class FilterSyntaxInvalidError < LdapError; end - class EntryOverflowError < LdapError; end - SearchScope_BaseObject = 0 SearchScope_SingleLevel = 1 SearchScope_WholeSubtree = 2 diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb new file mode 100644 index 00000000..bd2c74ad --- /dev/null +++ b/lib/net/ldap/error.rb @@ -0,0 +1,31 @@ +class Net::LDAP + class Error < StandardError; end + + class AlreadyOpenedError < Error; end + class SocketError < Error; end + class ConnectionRefusedError < Error; end + class NoOpenSSLError < Error; end + class NoStartTLSResultError < Error; end + class StartTLSError < Error; end + class EncryptionUnsupportedError < Error; end + class EncMethodUnsupportedError < Error; end + class AuthMethodUnsupportedError < Error; end + class BindingInformationInvalidError < Error; end + class NoBindResultError < Error; end + class SASLChallengeOverflowError < Error; end + class SearchSizeInvalidError < Error; end + class SearchScopeInvalidError < Error; end + class ResponseTypeInvalidError < Error; end + class ResponseMissingOrInvalidError < Error; end + class EmptyDNError < Error; end + class HashTypeUnsupportedError < Error; end + class OperatorError < Error; end + class SubstringFilterError < Error; end + class SearchFilterError < Error; end + class BERInvalidError < Error; end + class SearchFilterTypeUnknownError < Error; end + class BadAttributeError < Error; end + class FilterTypeUnknownError < Error; end + class FilterSyntaxInvalidError < Error; end + class EntryOverflowError < Error; end +end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 424f6bb3..96b542ac 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -2,14 +2,14 @@ class TestLDAPConnection < Test::Unit::TestCase def test_unresponsive_host - assert_raise Net::LDAP::LdapError do + assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end def test_blocked_port flexmock(TCPSocket).should_receive(:new).and_raise(SocketError) - assert_raise Net::LDAP::LdapError do + assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end From beac837aa8a8b408b8a12f9cda1ec3bf7b6a836c Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sun, 4 Jan 2015 21:27:43 +0900 Subject: [PATCH 330/435] Replace Net::LDAP::LdapError with Net::LDAP::Error in net/ldap/connection.rb --- lib/net/ldap/connection.rb | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 0e3d7e05..929415c8 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -12,13 +12,13 @@ def initialize(server) begin @conn = server[:socket] || TCPSocket.new(server[:host], server[:port]) rescue SocketError - raise Net::LDAP::LdapError, "No such address or other socket error." + raise Net::LDAP::Error, "No such address or other socket error." rescue Errno::ECONNREFUSED - raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}." + raise Net::LDAP::Error, "Server #{server[:host]} refused connection on port #{server[:port]}." rescue Errno::EHOSTUNREACH => error - raise Net::LDAP::LdapError, "Host #{server[:host]} was unreachable (#{error.message})" + raise Net::LDAP::Error, "Host #{server[:host]} was unreachable (#{error.message})" rescue Errno::ETIMEDOUT - raise Net::LDAP::LdapError, "Connection to #{server[:host]} timed out." + raise Net::LDAP::Error, "Connection to #{server[:host]} timed out." end if server[:encryption] @@ -42,7 +42,7 @@ def close end def self.wrap_with_ssl(io, tls_options = {}) - raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL + raise Net::LDAP::Error, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new @@ -67,7 +67,7 @@ def self.wrap_with_ssl(io, tls_options = {}) # successfully-opened @conn instance variable, which is a TCP connection. # Depending on the received arguments, we establish SSL, potentially # replacing the value of @conn accordingly. Don't generate any errors here - # if no encryption is requested. DO raise Net::LDAP::LdapError objects if encryption + # if no encryption is requested. DO raise Net::LDAP::Error objects if encryption # is requested and we have trouble setting it up. That includes if OpenSSL # is not set up on the machine. (Question: how does the Ruby OpenSSL # wrapper react in that case?) DO NOT filter exceptions raised by the @@ -105,16 +105,16 @@ def setup_encryption(args) pdu = queued_read(message_id) if pdu.nil? || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse - raise Net::LDAP::LdapError, "no start_tls result" + raise Net::LDAP::Error, "no start_tls result" end if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) else - raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" + raise Net::LDAP::Error, "start_tls failed: #{pdu.result_code}" end else - raise Net::LDAP::LdapError, "unsupported encryption method #{args[:method]}" + raise Net::LDAP::Error, "unsupported encryption method #{args[:method]}" end end @@ -225,7 +225,7 @@ def bind(auth) elsif meth == :gss_spnego bind_gss_spnego(auth) else - raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})" + raise Net::LDAP::Error, "Unsupported auth method (#{meth})" end end end @@ -241,7 +241,7 @@ def bind_simple(auth) ["", ""] end - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::Error, "Invalid binding information" unless (user && psw) message_id = next_msgid request = [ @@ -253,7 +253,7 @@ def bind_simple(auth) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::LdapError, "no bind result" + raise Net::LDAP::Error, "no bind result" end pdu @@ -283,7 +283,7 @@ def bind_simple(auth) def bind_sasl(auth) mech, cred, chall = auth[:mechanism], auth[:initial_credential], auth[:challenge_response] - raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall) + raise Net::LDAP::Error, "Invalid binding information" unless (mech && cred && chall) message_id = next_msgid @@ -298,16 +298,16 @@ def bind_sasl(auth) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::LdapError, "no bind result" + raise Net::LDAP::Error, "no bind result" end return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress - raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + raise Net::LDAP::Error, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) cred = chall.call(pdu.result_server_sasl_creds) } - raise Net::LDAP::LdapError, "why are we here?" + raise Net::LDAP::Error, "why are we here?" end private :bind_sasl @@ -326,7 +326,7 @@ def bind_gss_spnego(auth) require 'ntlm' user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::Error, "Invalid binding information" unless (user && psw) nego = proc { |challenge| t2_msg = NTLM::Message.parse(challenge) @@ -412,10 +412,10 @@ def search(args = nil) sort = args.fetch(:sort_controls, false) # arg validation - raise Net::LDAP::LdapError, "search base is required" unless base - raise Net::LDAP::LdapError, "invalid search-size" unless size >= 0 - raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) - raise Net::LDAP::LdapError, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) + raise Net::LDAP::Error, "search base is required" unless base + raise Net::LDAP::Error, "invalid search-size" unless size >= 0 + raise Net::LDAP::Error, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + raise Net::LDAP::Error, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) # arg transforms filter = Net::LDAP::Filter.construct(filter) if filter.is_a?(String) @@ -527,7 +527,7 @@ def search(args = nil) end break else - raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}" + raise Net::LDAP::Error, "invalid response-type in search: #{pdu.app_tag}" end end @@ -624,7 +624,7 @@ def modify(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyResponse - raise Net::LDAP::LdapError, "response missing or invalid" + raise Net::LDAP::Error, "response missing or invalid" end pdu @@ -638,7 +638,7 @@ def modify(args) # to the error message and the matched-DN returned by the server. #++ def add(args) - add_dn = args[:dn] or raise Net::LDAP::LdapError, "Unable to add empty DN" + add_dn = args[:dn] or raise Net::LDAP::Error, "Unable to add empty DN" add_attrs = [] a = args[:attributes] and a.each { |k, v| add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence @@ -651,7 +651,7 @@ def add(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse - raise Net::LDAP::LdapError, "response missing or invalid" + raise Net::LDAP::Error, "response missing or invalid" end pdu @@ -674,7 +674,7 @@ def rename(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyRDNResponse - raise Net::LDAP::LdapError.new "response missing or invalid" + raise Net::LDAP::Error.new "response missing or invalid" end pdu @@ -693,7 +693,7 @@ def delete(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::DeleteResponse - raise Net::LDAP::LdapError, "response missing or invalid" + raise Net::LDAP::Error, "response missing or invalid" end pdu From b412ca05f6b430eaa1ce97ac95885b4cf187b04a Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Jan 2015 08:43:48 +0900 Subject: [PATCH 331/435] Use SecureRandam to generate salt --- lib/net/ldap/password.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 3669dfcc..729e17e3 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -27,7 +27,7 @@ def generate(type, str) when :sha attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! when :ssha - srand; salt = (rand * 1000).to_i.to_s + srand; salt = SecureRandom.random_bytes(16) attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! else raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})" From c9d36cdf919e01996da5c61838c10c1bc59f3e81 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Jan 2015 08:51:11 +0900 Subject: [PATCH 332/435] Redefine Net::LDAP::LdapError to support backward compatibility --- lib/net/ldap/error.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index bd2c74ad..a5704b59 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -1,4 +1,10 @@ class Net::LDAP + class LdapError < StandardError + def message + "Deprecation warning: Net::LDAP::LdapError is no longer used. Use Net::LDAP::Error or rescue one of it's subclasses. \n" + super + end + end + class Error < StandardError; end class AlreadyOpenedError < Error; end From 937b8feaef8909b758d3b7b2217da4f772b712ff Mon Sep 17 00:00:00 2001 From: Rufus Post Date: Fri, 19 Dec 2014 15:34:26 +1100 Subject: [PATCH 333/435] Add rubocop to project This adds https://github.com/bbatsov/rubocop to the project with an auto generated `.rubocop_todo.yml`. The violations can be addressed over time without breaking the build. Also added is the `rake ci` task that runs `test` and `rubocop` only on mri. The `rubotest` task is the same is `rake ci` but will run on all rubies, the default rake task just runs test as per usual. Conflicts: net-ldap.gemspec --- .rubocop.yml | 5 + .rubocop_todo.yml | 462 ++++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 2 +- README.rdoc | 15 ++ Rakefile | 15 +- net-ldap.gemspec | 1 + 6 files changed, 497 insertions(+), 3 deletions(-) create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..85ffa202 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,5 @@ +inherit_from: .rubocop_todo.yml + +AllCops: + Exclude: + - 'pkg/**/*' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..5a5dcbc7 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,462 @@ +# This configuration was generated by `rubocop --auto-gen-config` +# on 2014-12-19 15:32:44 +1100 using RuboCop version 0.28.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 12 +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Enabled: false + +# Offense count: 1 +# Configuration parameters: AlignWith, SupportedStyles. +Lint/EndAlignment: + Enabled: false + +# Offense count: 1 +Lint/RescueException: + Enabled: false + +# Offense count: 1 +Lint/ShadowingOuterLocalVariable: + Enabled: false + +# Offense count: 9 +# Cop supports --auto-correct. +Lint/UnusedBlockArgument: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +Lint/UnusedMethodArgument: + Enabled: false + +# Offense count: 7 +Lint/UselessAssignment: + Enabled: false + +# Offense count: 47 +Metrics/AbcSize: + Max: 114 + +# Offense count: 11 +Metrics/BlockNesting: + Max: 4 + +# Offense count: 9 +# Configuration parameters: CountComments. +Metrics/ClassLength: + Max: 470 + +# Offense count: 20 +Metrics/CyclomaticComplexity: + Max: 41 + +# Offense count: 193 +# Configuration parameters: AllowURI, URISchemes. +Metrics/LineLength: + Max: 360 + +# Offense count: 71 +# Configuration parameters: CountComments. +Metrics/MethodLength: + Max: 130 + +# Offense count: 13 +Metrics/PerceivedComplexity: + Max: 36 + +# Offense count: 1 +Style/AccessorMethodName: + Enabled: false + +# Offense count: 4 +# Cop supports --auto-correct. +Style/AlignArray: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/AlignParameters: + Enabled: false + +# Offense count: 36 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/AndOr: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/BarePercentLiterals: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/BlockComments: + Enabled: false + +# Offense count: 20 +# Cop supports --auto-correct. +Style/Blocks: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/BracesAroundHashParameters: + Enabled: false + +# Offense count: 4 +# Configuration parameters: IndentWhenRelativeTo, SupportedStyles, IndentOneStep. +Style/CaseIndentation: + Enabled: false + +# Offense count: 4 +# Cop supports --auto-correct. +Style/CharacterLiteral: + Enabled: false + +# Offense count: 22 +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/ClassAndModuleChildren: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/ClassCheck: + Enabled: false + +# Offense count: 13 +# Cop supports --auto-correct. +Style/ColonMethodCall: + Enabled: false + +# Offense count: 2 +# Configuration parameters: Keywords. +Style/CommentAnnotation: + Enabled: false + +# Offense count: 86 +Style/ConstantName: + Enabled: false + +# Offense count: 18 +# Cop supports --auto-correct. +Style/DeprecatedHashMethods: + Enabled: false + +# Offense count: 46 +Style/Documentation: + Enabled: false + +# Offense count: 23 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/DotPosition: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/ElseAlignment: + Enabled: false + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: AllowAdjacentOneLineDefs. +Style/EmptyLineBetweenDefs: + Enabled: false + +# Offense count: 9 +# Cop supports --auto-correct. +Style/EmptyLines: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/EmptyLinesAroundClassBody: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/EmptyLinesAroundModuleBody: + Enabled: false + +# Offense count: 3 +Style/EvenOdd: + Enabled: false + +# Offense count: 1 +# Configuration parameters: Exclude. +Style/FileName: + Enabled: false + +# Offense count: 9 +# Configuration parameters: AllowedVariables. +Style/GlobalVars: + Enabled: false + +# Offense count: 3 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Enabled: false + +# Offense count: 150 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/HashSyntax: + Enabled: false + +# Offense count: 8 +# Configuration parameters: MaxLineLength. +Style/IfUnlessModifier: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/IndentHash: + Enabled: false + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: Width. +Style/IndentationWidth: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +Style/LeadingCommentSpace: + Enabled: false + +# Offense count: 21 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/MethodDefParentheses: + Enabled: false + +# Offense count: 1 +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/MethodName: + Enabled: false + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/MultilineOperationIndentation: + Enabled: false + +# Offense count: 1 +Style/MultilineTernaryOperator: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/NegatedIf: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/NegatedWhile: + Enabled: false + +# Offense count: 3 +# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. +Style/Next: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/NilComparison: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: IncludeSemanticChanges. +Style/NonNilCheck: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/Not: + Enabled: false + +# Offense count: 10 +# Cop supports --auto-correct. +Style/NumericLiterals: + MinDigits: 8 + +# Offense count: 3 +Style/OpMethod: + Enabled: false + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: AllowSafeAssignment. +Style/ParenthesesAroundCondition: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Enabled: false + +# Offense count: 11 +# Cop supports --auto-correct. +Style/PerlBackrefs: + Enabled: false + +# Offense count: 9 +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/RaiseArgs: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantBegin: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Enabled: false + +# Offense count: 7 +# Cop supports --auto-correct. +Style/RedundantSelf: + Enabled: false + +# Offense count: 1 +# Configuration parameters: MaxSlashes. +Style/RegexpLiteral: + Enabled: false + +# Offense count: 2 +Style/RescueModifier: + Enabled: false + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: AllowAsExpressionSeparator. +Style/Semicolon: + Enabled: false + +# Offense count: 61 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/SignalException: + Enabled: false + +# Offense count: 2 +# Configuration parameters: Methods. +Style/SingleLineBlockParams: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +Style/SingleSpaceBeforeFirstArg: + Enabled: false + +# Offense count: 24 +# Cop supports --auto-correct. +Style/SpaceAfterComma: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/SpaceAroundEqualsInParameterDefault: + Enabled: false + +# Offense count: 8 +# Cop supports --auto-correct. +Style/SpaceAroundOperators: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/SpaceBeforeBlockBraces: + Enabled: false + +# Offense count: 18 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +Style/SpaceInsideBlockBraces: + Enabled: false + +# Offense count: 37 +# Cop supports --auto-correct. +Style/SpaceInsideBrackets: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles. +Style/SpaceInsideHashLiteralBraces: + Enabled: false + +# Offense count: 20 +# Cop supports --auto-correct. +Style/SpaceInsideParens: + Enabled: false + +# Offense count: 5 +# Cop supports --auto-correct. +Style/SpecialGlobalVars: + Enabled: false + +# Offense count: 645 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/StringLiterals: + Enabled: false + +# Offense count: 10 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +Style/SymbolProc: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +Style/TrailingBlankLines: + Enabled: false + +# Offense count: 9 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. +Style/TrailingComma: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, Whitelist. +Style/TrivialAccessors: + Enabled: false + +# Offense count: 5 +# Cop supports --auto-correct. +Style/UnneededPercentQ: + Enabled: false + +# Offense count: 1 +# Configuration parameters: MaxLineLength. +Style/WhileUntilModifier: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: WordRegex. +Style/WordArray: + MinSize: 2 diff --git a/.travis.yml b/.travis.yml index c1247468..311ed4c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: - if [ "$INTEGRATION" = "openldap" ]; then ./script/install-openldap; fi - bundle install -script: bundle exec rake +script: bundle exec rake ci matrix: allow_failures: diff --git a/README.rdoc b/README.rdoc index e34162b8..b8331f7c 100644 --- a/README.rdoc +++ b/README.rdoc @@ -37,12 +37,27 @@ sources. Simply require either 'net-ldap' or 'net/ldap'. +== Develop + +This task will run the test suite and the +{RuboCop}[https://github.com/bbatsov/rubocop] static code analyzer. + + rake rubotest + +To run the integration tests against an LDAP server: + + cd test/support/vm/openldap + vagrant up + cd ../../../.. + INTEGRATION=openldap bundle exec rake rubotest + == Release This section is for gem maintainers to cut a new version of the gem. * Update lib/net/ldap/version.rb to next version number X.X.X following {semver}(http://semver.org/). * Update `History.rdoc`. Get latest changes with `git log --oneline vLAST_RELEASE..HEAD | grep Merge` + * On the master branch, run `script/release` :include: Contributors.rdoc diff --git a/Rakefile b/Rakefile index edc8fc75..85a70153 100644 --- a/Rakefile +++ b/Rakefile @@ -3,11 +3,22 @@ # vim: syntax=ruby require 'rake/testtask' +require 'rubocop/rake_task' +require 'bundler' + +RuboCop::RakeTask.new Rake::TestTask.new do |t| - t.libs << "test" + t.libs << 'test' t.test_files = FileList['test/**/test_*.rb'] t.verbose = true + t.description = 'Run tests, set INTEGRATION=openldap to run integration tests, INTEGRATION_HOST and INTEGRATION_PORT are also supported' end -task :default => :test +desc 'Run tests and RuboCop (RuboCop runs on mri only)' +task ci: Bundler.current_ruby.mri? ? [:test, :rubocop] : [:test] + +desc 'Run tests and RuboCop' +task rubotest: [:test, :rubocop] + +task default: :test diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 76299ac7..7cdd29db 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -31,4 +31,5 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_development_dependency("flexmock", "~> 1.3") s.add_development_dependency("rake", "~> 10.0") + s.add_development_dependency("rubocop", "~> 0.28.0") end From 120d8c8bf33b950ee4ada8059acb879aa33b6e4e Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Jan 2015 09:10:34 +0900 Subject: [PATCH 334/435] Replace Net::LDAP::Error with proper subsclasses --- lib/net/ldap/connection.rb | 42 +++++++++++++++++++------------------- lib/net/ldap/error.rb | 1 + 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 929415c8..f23fa106 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -42,7 +42,7 @@ def close end def self.wrap_with_ssl(io, tls_options = {}) - raise Net::LDAP::Error, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL + raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new @@ -105,16 +105,16 @@ def setup_encryption(args) pdu = queued_read(message_id) if pdu.nil? || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse - raise Net::LDAP::Error, "no start_tls result" + raise Net::LDAP::NoStartTLSResultError, "no start_tls result" end if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) else - raise Net::LDAP::Error, "start_tls failed: #{pdu.result_code}" + raise Net::LDAP::StartTlSError, "start_tls failed: #{pdu.result_code}" end else - raise Net::LDAP::Error, "unsupported encryption method #{args[:method]}" + raise Net::LDAP::EncMethodUnsupportedError, "unsupported encryption method #{args[:method]}" end end @@ -225,7 +225,7 @@ def bind(auth) elsif meth == :gss_spnego bind_gss_spnego(auth) else - raise Net::LDAP::Error, "Unsupported auth method (#{meth})" + raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})" end end end @@ -241,7 +241,7 @@ def bind_simple(auth) ["", ""] end - raise Net::LDAP::Error, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) message_id = next_msgid request = [ @@ -253,7 +253,7 @@ def bind_simple(auth) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::Error, "no bind result" + raise Net::LDAP::NoBindResultError, "no bind result" end pdu @@ -283,7 +283,7 @@ def bind_simple(auth) def bind_sasl(auth) mech, cred, chall = auth[:mechanism], auth[:initial_credential], auth[:challenge_response] - raise Net::LDAP::Error, "Invalid binding information" unless (mech && cred && chall) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall) message_id = next_msgid @@ -298,16 +298,16 @@ def bind_sasl(auth) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::Error, "no bind result" + raise Net::LDAP::NoBindResultError, "no bind result" end return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress - raise Net::LDAP::Error, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) cred = chall.call(pdu.result_server_sasl_creds) } - raise Net::LDAP::Error, "why are we here?" + raise Net::LDAP::SASLChallengeOverflowError, "why are we here?" end private :bind_sasl @@ -326,7 +326,7 @@ def bind_gss_spnego(auth) require 'ntlm' user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::Error, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) nego = proc { |challenge| t2_msg = NTLM::Message.parse(challenge) @@ -412,9 +412,9 @@ def search(args = nil) sort = args.fetch(:sort_controls, false) # arg validation - raise Net::LDAP::Error, "search base is required" unless base - raise Net::LDAP::Error, "invalid search-size" unless size >= 0 - raise Net::LDAP::Error, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + raise Net::LDAP::NoSearchBaseError, "search base is required" unless base + raise Net::LDAP::SearchSizeInvalidError, "invalid search-size" unless size >= 0 + raise Net::LDAP::SearchScopeInvalidError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) raise Net::LDAP::Error, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) # arg transforms @@ -527,7 +527,7 @@ def search(args = nil) end break else - raise Net::LDAP::Error, "invalid response-type in search: #{pdu.app_tag}" + raise Net::LDAP::ResponseTypeInvalidError, "invalid response-type in search: #{pdu.app_tag}" end end @@ -624,7 +624,7 @@ def modify(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyResponse - raise Net::LDAP::Error, "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end pdu @@ -638,7 +638,7 @@ def modify(args) # to the error message and the matched-DN returned by the server. #++ def add(args) - add_dn = args[:dn] or raise Net::LDAP::Error, "Unable to add empty DN" + add_dn = args[:dn] or raise Net::LDAP::EmptyDNError, "Unable to add empty DN" add_attrs = [] a = args[:attributes] and a.each { |k, v| add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence @@ -651,7 +651,7 @@ def add(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse - raise Net::LDAP::Error, "response missing or invalid" + raise Net::LDAP::ResponseMissingError, "response missing or invalid" end pdu @@ -674,7 +674,7 @@ def rename(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyRDNResponse - raise Net::LDAP::Error.new "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError.new "response missing or invalid" end pdu @@ -693,7 +693,7 @@ def delete(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::DeleteResponse - raise Net::LDAP::Error, "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end pdu diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index a5704b59..c9a25f90 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -12,6 +12,7 @@ class SocketError < Error; end class ConnectionRefusedError < Error; end class NoOpenSSLError < Error; end class NoStartTLSResultError < Error; end + class NoSearchBaseError < Error; end class StartTLSError < Error; end class EncryptionUnsupportedError < Error; end class EncMethodUnsupportedError < Error; end From b133b317b320c051d25dfcbcd2dfb2dca5261972 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 7 Jan 2015 12:35:01 -0800 Subject: [PATCH 335/435] unescape always to_s. test --- lib/net/ldap/filter.rb | 13 ++----------- test/test_filter.rb | 5 +++++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 1f43ced2..4f5da3e5 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -644,18 +644,9 @@ def match(entry) end ## - # If the argument is a string, converts escaped characters (e.g., "\\28") to unescaped characters. - # If the argument is a number, just return as-is. - # Otherwise, an exception is thrown and the rhs argument is rejected. - # ("("). + # Converts escaped characters (e.g., "\\28") to unescaped characters def unescape(right) - if defined? right.gsub - right.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") } - elsif right.is_a? Fixnum - right.to_s - else - raise ArgumentError, "Did not know how to convert argument \"#{right}\" into the rhs of an LDAP filter" - end + right.to_s.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") } end private :unescape diff --git a/test/test_filter.rb b/test/test_filter.rb index eb6192d0..139612a1 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -215,4 +215,9 @@ def test_parse_ber_escapes_characters filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)) assert_equal "(objectclass=#{escaped}*#{escaped}*#{escaped})", filter.to_s end + + def test_unescape_fixnums + filter = Net::LDAP::Filter.eq("objectclass", 3) + assert_equal "\xA3\x10\x04\vobjectclass\x04\x013".b, filter.to_ber + end end From f046564db16d2c19dc16f2307bcf7f86250a769c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 7 Jan 2015 12:52:24 -0800 Subject: [PATCH 336/435] use if for conjunction conditional --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 53c5fde2..7ed0bdb5 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -577,7 +577,7 @@ def search(args = nil) # in the exceptional case some messages were *not* consumed from the queue, # instrument the event but do not fail. - unless messages.nil? or messages.empty? + if !messages.nil? && !messages.empty? instrument "search_messages_unread.net_ldap_connection", message_id: message_id, messages: messages end From 82bf3124b42bdccaeeea19cdd3bce4d52191f73d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 7 Jan 2015 12:59:06 -0800 Subject: [PATCH 337/435] add contributor --- Contributors.rdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/Contributors.rdoc b/Contributors.rdoc index b3b25ff6..e40b20db 100644 --- a/Contributors.rdoc +++ b/Contributors.rdoc @@ -21,3 +21,4 @@ Contributions since: * nowhereman * David J. Lee (DavidJLee) * Cody Cutrer (ccutrer) +* WoodsBagotAndreMarquesLee From 20d3a430747472f14b99a6487cfab026b1dcc493 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 9 Jan 2015 23:30:34 +0900 Subject: [PATCH 338/435] Raise ArgumentError in arg validation of Net::LDAP::Connection#search --- lib/net/ldap/connection.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index f23fa106..23d9f1e4 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -412,10 +412,10 @@ def search(args = nil) sort = args.fetch(:sort_controls, false) # arg validation - raise Net::LDAP::NoSearchBaseError, "search base is required" unless base - raise Net::LDAP::SearchSizeInvalidError, "invalid search-size" unless size >= 0 - raise Net::LDAP::SearchScopeInvalidError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) - raise Net::LDAP::Error, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) + raise ArgumentError, "search base is required" unless base + raise ArgumentError, "invalid search-size" unless size >= 0 + raise ArgumentError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope) + raise ArgumentError, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref) # arg transforms filter = Net::LDAP::Filter.construct(filter) if filter.is_a?(String) From 94d2d6a2b79764ee4de3dfad05dcef8dde99a0d4 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 10 Jan 2015 07:25:10 +0900 Subject: [PATCH 339/435] Remove the dangling srand --- lib/net/ldap/password.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 729e17e3..28406f03 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -23,11 +23,11 @@ class << self def generate(type, str) case type when :md5 - attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! + attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! when :sha - attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! + attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! when :ssha - srand; salt = SecureRandom.random_bytes(16) + salt = SecureRandom.random_bytes(16) attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! else raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})" From 5a2b2cac2e6e6bc64168bc4a39b0fe8a8cdbb630 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 10 Jan 2015 07:26:42 +0900 Subject: [PATCH 340/435] Correct trailing white spaces --- lib/net/ldap/filter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 355e0f29..0ab847b8 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -310,8 +310,8 @@ def parse_ber(ber) present?(ber.to_s) when 0xa9 # context-specific constructed 9, "extensible comparison" raise Net::LDAP::SearchFilterError, "Invalid extensible search filter, should be at least two elements" if ber.size < 2 - - # Reassembles the extensible filter parts + + # Reassembles the extensible filter parts # (["sn", "2.4.6.8.10", "Barbara Jones", '1']) type = value = dn = rule = nil ber.each do |element| From 4feab6f239399137d780c94ce303663f5546fd56 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 16 Jan 2015 11:22:07 -0800 Subject: [PATCH 341/435] disable rubocop in ci Unblocks https://github.com/ruby-ldap/ruby-net-ldap/pull/183. There is a proposed fix in https://github.com/ruby-ldap/ruby-net-ldap/pull/185, but it's not ready yet. --- Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 85a70153..76ec8c09 100644 --- a/Rakefile +++ b/Rakefile @@ -16,9 +16,9 @@ Rake::TestTask.new do |t| end desc 'Run tests and RuboCop (RuboCop runs on mri only)' -task ci: Bundler.current_ruby.mri? ? [:test, :rubocop] : [:test] +task ci: [:test] desc 'Run tests and RuboCop' task rubotest: [:test, :rubocop] -task default: :test +task default: Bundler.current_ruby.mri? ? [:test, :rubocop] : [:test] From 0c62e75e7c6aa1d93e7ca1659b9c2eb073d6c5d8 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 21 Jan 2015 14:27:47 -0800 Subject: [PATCH 342/435] release 0.11 --- History.rdoc | 9 +++++++++ lib/net/ldap/version.rb | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index c3a786a0..fa7ff5a1 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,12 @@ +=== Net::LDAP 0.11 +* Major enhancements: + * #183 Specific errors subclassing Net::LDAP::Error +* Bug fixes: + * #176 Fix nil tls options + * #184 Search guards against nil queued reads. Connection#unescape handles numerics +* Code clean-up: + * #180 Refactor connection establishment + === Net::LDAP 0.10.1 * Bug fixes: * Fix Integer BER encoding of signed values diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 5ecad815..98d557cf 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.10.1" + VERSION = "0.11" end end From c326a4d7623974402979a3aa5ea13299bf4c4590 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 21 Jan 2015 14:33:07 -0800 Subject: [PATCH 343/435] Release 0.11 From 1d5f08874f0bfd0aba3efd13f3c12ad31c12e52b Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 17 Apr 2015 01:24:33 +0900 Subject: [PATCH 344/435] README.rdoc: fix travis link --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index b8331f7c..89b2d7d7 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,4 @@ -= Net::LDAP for Ruby {}[https://travis-ci.org/github/ruby-net-ldap] += Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap] == Description From 141333e2ddfdb5b0b395c7d3c7ed37c2a7fba0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Wed, 13 May 2015 14:45:49 +0200 Subject: [PATCH 345/435] Remove meaningless shebang Rakefile has no executable bit and does nothing by default. --- Rakefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Rakefile b/Rakefile index 76ec8c09..51ab55dc 100644 --- a/Rakefile +++ b/Rakefile @@ -1,4 +1,3 @@ -#!/usr/bin/env rake # -*- ruby encoding: utf-8 -*- # vim: syntax=ruby From 91a8518bc7322bf6db11efffac9d8b43ad2e1673 Mon Sep 17 00:00:00 2001 From: ojab Date: Wed, 20 May 2015 13:14:07 +0000 Subject: [PATCH 346/435] Fix Travis CI build --- script/install-openldap | 1 + 1 file changed, 1 insertion(+) diff --git a/script/install-openldap b/script/install-openldap index 9547f0ff..e9575500 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -6,6 +6,7 @@ BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\ + DEBIAN_FRONTEND=noninteractive sudo -E apt-get update -y --force-yes && \ DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils gnutls-bin ssl-cert sudo /etc/init.d/slapd stop From c17a6a6f1649e9943f3000556534f4172d25e199 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 21 Apr 2015 14:47:38 +0900 Subject: [PATCH 347/435] mv "sudo" from script/install-openldap to .travis.yml --- .travis.yml | 2 +- script/install-openldap | 60 ++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.travis.yml b/.travis.yml index 311ed4c1..8f41f070 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ env: - INTEGRATION=openldap install: - - if [ "$INTEGRATION" = "openldap" ]; then ./script/install-openldap; fi + - if [ "$INTEGRATION" = "openldap" ]; then sudo script/install-openldap; fi - bundle install script: bundle exec rake ci diff --git a/script/install-openldap b/script/install-openldap index e9575500..b9efac98 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -6,69 +6,69 @@ BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )" SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )" dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\ - DEBIAN_FRONTEND=noninteractive sudo -E apt-get update -y --force-yes && \ - DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y --force-yes slapd time ldap-utils gnutls-bin ssl-cert + DEBIAN_FRONTEND=noninteractive apt-get update -y --force-yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes slapd time ldap-utils gnutls-bin ssl-cert -sudo /etc/init.d/slapd stop +/etc/init.d/slapd stop TMPDIR=$(mktemp -d) cd $TMPDIR # Delete data and reconfigure. -sudo cp -v /var/lib/ldap/DB_CONFIG ./DB_CONFIG -sudo rm -rf /etc/ldap/slapd.d/* -sudo rm -rf /var/lib/ldap/* -sudo cp -v ./DB_CONFIG /var/lib/ldap/DB_CONFIG -sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/slapd.conf.ldif +cp -v /var/lib/ldap/DB_CONFIG ./DB_CONFIG +rm -rf /etc/ldap/slapd.d/* +rm -rf /var/lib/ldap/* +cp -v ./DB_CONFIG /var/lib/ldap/DB_CONFIG +slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/slapd.conf.ldif # Load memberof and ref-int overlays and configure them. -sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/memberof.ldif +slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/memberof.ldif # Load retcode overlay and configure -sudo slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/retcode.ldif +slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/retcode.ldif # Add base domain. -sudo slapadd -F /etc/ldap/slapd.d < /etc/ssl/private/cakey.pem" +sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem" -sudo sh -c "cat > /etc/ssl/ca.info < /etc/ssl/ca.info < /etc/ssl/ldap01.info < /etc/ssl/ldap01.info < Date: Thu, 21 May 2015 19:27:44 -0700 Subject: [PATCH 348/435] Remove obsolete rbx-19mode from Travis There are no language modes in Rubinius anymore. Using rbx-2 will run the most recent release of Rubinius 2.x. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8f41f070..e959ff4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ rvm: - 2.1.2 # optional - jruby-19mode - - rbx-19mode - rbx-2 env: From 72d4d46363530f7c9345249c99dfb065935cc067 Mon Sep 17 00:00:00 2001 From: George Millo Date: Thu, 25 Jun 2015 17:32:41 +0200 Subject: [PATCH 349/435] fix incorrect error class name --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 5e735f53..b51bcc10 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -652,7 +652,7 @@ def add(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse - raise Net::LDAP::ResponseMissingError, "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end pdu From 906bd1e8ae72e55816235d888538deef79ba7d19 Mon Sep 17 00:00:00 2001 From: ojab Date: Fri, 22 May 2015 03:52:57 +0000 Subject: [PATCH 350/435] Update rubies in .travis.yml Also add "test-unit" gem to gemspec in order to prevent new rubies failures --- .travis.yml | 8 ++++++-- net-ldap.gemspec | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e959ff4f..4131d6e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,12 @@ language: ruby rvm: - 1.9.3 - 2.0.0 - - 2.1.2 + - 2.1 + - 2.2 # optional + - ruby-head - jruby-19mode + - jruby-head - rbx-2 env: @@ -18,8 +21,9 @@ script: bundle exec rake ci matrix: allow_failures: + - rvm: ruby-head - rvm: jruby-19mode - - rvm: rbx-19mode + - rvm: jruby-head - rvm: rbx-2 fast_finish: true diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 7cdd29db..97c12906 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -32,4 +32,5 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_development_dependency("flexmock", "~> 1.3") s.add_development_dependency("rake", "~> 10.0") s.add_development_dependency("rubocop", "~> 0.28.0") + s.add_development_dependency("test-unit") end From a83fb32025ec66801e2a4e48cfe60e9117709ff8 Mon Sep 17 00:00:00 2001 From: Brian Weaver Date: Tue, 25 Aug 2015 14:20:09 -0400 Subject: [PATCH 351/435] Server strings are always UTF-8 --- lib/net/ber.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index b8992a92..f7f1bdde 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -296,9 +296,8 @@ def to_arr class Net::BER::BerIdentifiedString < String attr_accessor :ber_identifier def initialize args + args.force_encoding('UTF-8') if args.respond_to(:force_encoding) super args - # LDAP uses UTF-8 encoded strings - self.encode('UTF-8') if self.respond_to?(:encoding) rescue self end end From 04125c73f71b9da207d1a5cb31996f73f072d33c Mon Sep 17 00:00:00 2001 From: Brian Weaver Date: Tue, 25 Aug 2015 14:49:43 -0400 Subject: [PATCH 352/435] Correctly encode to UTF-8 when possible --- lib/net/ber.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index f7f1bdde..b4b9e9da 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -296,8 +296,11 @@ def to_arr class Net::BER::BerIdentifiedString < String attr_accessor :ber_identifier def initialize args - args.force_encoding('UTF-8') if args.respond_to(:force_encoding) - super args + super begin + args.respond_to?(:encode) ? args.encode('UTF-8') : args + rescue + args + end end end From b3e67d37cee7008e65f201674af00475a214bae8 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Thu, 27 Aug 2015 11:57:55 +0900 Subject: [PATCH 353/435] Raise Net::LDAP::ConnectionRefusedError when new connection is refused. Now Net::LDAP::Connection.new raises Net::LDAP::Error even if the connection refused. It's hard for some application to reconnect it only when refused. --- lib/net/ldap/connection.rb | 2 +- test/test_ldap_connection.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index b51bcc10..8e0e8c18 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -14,7 +14,7 @@ def initialize(server) rescue SocketError raise Net::LDAP::Error, "No such address or other socket error." rescue Errno::ECONNREFUSED - raise Net::LDAP::Error, "Server #{server[:host]} refused connection on port #{server[:port]}." + raise Net::LDAP::ConnectionRefusedError, "Server #{server[:host]} refused connection on port #{server[:port]}." rescue Errno::EHOSTUNREACH => error raise Net::LDAP::Error, "Host #{server[:host]} was unreachable (#{error.message})" rescue Errno::ETIMEDOUT diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 96b542ac..5b90ae22 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -14,6 +14,13 @@ def test_blocked_port end end + def test_connection_refused + flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) + assert_raise Net::LDAP::ConnectionRefusedError do + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + end + end + def test_raises_unknown_exceptions error = Class.new(StandardError) flexmock(TCPSocket).should_receive(:new).and_raise(error) From 4f0f4b2efe059c0bd56a2aa5427a9cb5793e64e7 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 28 Aug 2015 14:12:36 +0900 Subject: [PATCH 354/435] Raising Net::LDAP::ConnectionRefusedError, shows deprecation warning. --- lib/net/ldap/error.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index c9a25f90..1b24b5a3 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -9,7 +9,21 @@ class Error < StandardError; end class AlreadyOpenedError < Error; end class SocketError < Error; end - class ConnectionRefusedError < Error; end + class ConnectionRefusedError < Error; + def initialize(*args) + warn warning_message + super + end + + def message + warning_message + super + end + + private + def warning_message + "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead. \n" + end + end class NoOpenSSLError < Error; end class NoStartTLSResultError < Error; end class NoSearchBaseError < Error; end From d20ee69c7e936a152f73dc58a1660286dc266cff Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 28 Aug 2015 16:02:45 +0900 Subject: [PATCH 355/435] ConnectionRefusedError does not change the original error message --- lib/net/ldap/error.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index 1b24b5a3..38b4a4a5 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -11,17 +11,18 @@ class AlreadyOpenedError < Error; end class SocketError < Error; end class ConnectionRefusedError < Error; def initialize(*args) - warn warning_message + warn_deprecation_message super end def message - warning_message + super + warn_deprecation_message + super end private - def warning_message - "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead. \n" + def warn_deprecation_message + warn "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead." end end class NoOpenSSLError < Error; end From b0bf5511520edb7a27874967bdd499e00dba89cb Mon Sep 17 00:00:00 2001 From: Alex Stockwell Date: Wed, 16 Sep 2015 19:12:45 -0700 Subject: [PATCH 356/435] obscure auth password upon #inspect, added test, closes #216 --- lib/net/ldap.rb | 5 +++++ test/test_ldap.rb | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 75b463fb..35c9c54d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1195,6 +1195,11 @@ def paged_searches_supported? @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) end + # Mask auth password + def inspect + super.gsub @auth[:password], "*******" if @auth[:password] + end + private # Yields an open connection if there is one, otherwise establishes a new diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 9704b346..6122b8df 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -57,4 +57,10 @@ def test_instrument_search_with_size assert_equal "(uid=user1)", payload[:filter] assert_equal result.size, payload[:size] end + + def test_obscure_auth + password = "opensesame" + @subject.auth "joe_user", password + assert_not_include(@subject.inspect, password) + end end From 02ec36edbb862d510ab4c6ecc7782b1bd1099f3b Mon Sep 17 00:00:00 2001 From: Alex Stockwell Date: Wed, 16 Sep 2015 19:28:09 -0700 Subject: [PATCH 357/435] fixed oversight bug where inspecting Net::LDAP with anonymous auth returned nil --- lib/net/ldap.rb | 4 +++- test/test_ldap.rb | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 35c9c54d..635aa97d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1197,7 +1197,9 @@ def paged_searches_supported? # Mask auth password def inspect - super.gsub @auth[:password], "*******" if @auth[:password] + inspected = super + inspected.gsub! @auth[:password], "*******" if @auth[:password] + inspected end private diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 6122b8df..f30416b2 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -60,6 +60,7 @@ def test_instrument_search_with_size def test_obscure_auth password = "opensesame" + assert_include(@subject.inspect, "anonymous") @subject.auth "joe_user", password assert_not_include(@subject.inspect, password) end From b4a3bd2ddc90c0decd664c69a51023820e1548a7 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 18 Sep 2015 17:54:07 +0900 Subject: [PATCH 358/435] Capture the result of stderr to check the warning message. --- test/test_ldap_connection.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 5b90ae22..4fa7b22d 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -1,6 +1,14 @@ require_relative 'test_helper' class TestLDAPConnection < Test::Unit::TestCase + def capture_stderr + stderr, $stderr = $stderr, StringIO.new + yield + $stderr.string + ensure + $stderr = stderr + end + def test_unresponsive_host assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) @@ -16,9 +24,12 @@ def test_blocked_port def test_connection_refused flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) - assert_raise Net::LDAP::ConnectionRefusedError do - Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + stderr = capture_stderr do + assert_raise Net::LDAP::ConnectionRefusedError do + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + end end + assert_equal("Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead.\n", stderr) end def test_raises_unknown_exceptions From 9be7363d8e9a04e14866768d8ccc166e24c77e84 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 10:29:49 -0700 Subject: [PATCH 359/435] add script/changelog --- README.rdoc | 2 +- script/changelog | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100755 script/changelog diff --git a/README.rdoc b/README.rdoc index 89b2d7d7..7980c403 100644 --- a/README.rdoc +++ b/README.rdoc @@ -56,7 +56,7 @@ To run the integration tests against an LDAP server: This section is for gem maintainers to cut a new version of the gem. * Update lib/net/ldap/version.rb to next version number X.X.X following {semver}(http://semver.org/). -* Update `History.rdoc`. Get latest changes with `git log --oneline vLAST_RELEASE..HEAD | grep Merge` +* Update `History.rdoc`. Get latest changes with `script/changelog` * On the master branch, run `script/release` diff --git a/script/changelog b/script/changelog new file mode 100755 index 00000000..cda2ad83 --- /dev/null +++ b/script/changelog @@ -0,0 +1,47 @@ +#!/bin/bash +# Usage: script/changelog [-r ] [-b ] [-h ] +# +# repo: BASE string of GitHub REPOsitory url. e.g. "user_or_org/REPOsitory". Defaults to git remote url. +# base: git ref to compare from. e.g. "v1.3.1". Defaults to latest git tag. +# head: git ref to compare to. Defaults to "HEAD". +# +# Generate a changelog preview from pull requests merged between `base` and +# `head`. +# +# https://github.com/jch/release-scripts/blob/master/changelog +set -e + +[ $# -eq 0 ] && set -- --help +while [[ $# > 1 ]] +do + key="$1" + case $key in + -r|--repo) + repo="$2" + shift + ;; + -b|--base) + base="$2" + shift + ;; + -h|--head) + head="$2" + shift + ;; + *) + ;; + esac + shift +done + +repo="${repo:-$(git remote -v | grep push | awk '{print $2}' | cut -d'/' -f4- | sed 's/\.git//')}" +base="${base:-$(git tag -l | sort -t. -k 1,1n -k 2,2n -k 3,3n | tail -n 1)}" +head="${head:-HEAD}" +api_url="https://api.github.com" + +# get merged PR's. Better way is to query the API for these, but this is easier +for pr in $(git log --oneline $base..$head | grep "Merge pull request" | awk '{gsub("#",""); print $5}') +do + # frustrated with trying to pull out the right values, fell back to ruby + curl -s "$api_url/repos/$repo/pulls/$pr" | ruby -rjson -e 'pr=JSON.parse(STDIN.read); puts "* #{pr[%q(title)]} {##{pr[%q(number)]}}[#{pr[%q(html_url)]}]"' +done From f45e7ff32c7c6e7faee877bba7409006eb3cee4b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 10:30:23 -0700 Subject: [PATCH 360/435] bump version 0.12 --- History.rdoc | 13 +++++++++++++ lib/net/ldap/version.rb | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index fa7ff5a1..70e92eee 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,16 @@ +=== Net::LDAP 0.12 + +* Correctly set BerIdentifiedString values to UTF-8 {#212}[https://github.com/ruby-ldap/ruby-net-ldap/pull/212] +* Raise Net::LDAP::ConnectionRefusedError when new connection is refused. {#213}[https://github.com/ruby-ldap/ruby-net-ldap/pull/213] +* obscure auth password upon #inspect, added test, closes #216 {#217}[https://github.com/ruby-ldap/ruby-net-ldap/pull/217] +* Fixing incorrect error class name {#207}[https://github.com/ruby-ldap/ruby-net-ldap/pull/207] +* Travis update {#205}[https://github.com/ruby-ldap/ruby-net-ldap/pull/205] +* Remove obsolete rbx-19mode from Travis {#204}[https://github.com/ruby-ldap/ruby-net-ldap/pull/204] +* mv "sudo" from script/install-openldap to .travis.yml {#199}[https://github.com/ruby-ldap/ruby-net-ldap/pull/199] +* Remove meaningless shebang {#200}[https://github.com/ruby-ldap/ruby-net-ldap/pull/200] +* Fix Travis CI build {#202}[https://github.com/ruby-ldap/ruby-net-ldap/pull/202] +* README.rdoc: fix travis link {#195}[https://github.com/ruby-ldap/ruby-net-ldap/pull/195] + === Net::LDAP 0.11 * Major enhancements: * #183 Specific errors subclassing Net::LDAP::Error diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 98d557cf..1d0f6b08 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.11" + VERSION = "0.12" end end From c005e67a5796e36c5c37771368717df9cd0543c9 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 10:30:40 -0700 Subject: [PATCH 361/435] update readme for release instructions --- README.rdoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rdoc b/README.rdoc index 7980c403..7f774e31 100644 --- a/README.rdoc +++ b/README.rdoc @@ -55,10 +55,11 @@ To run the integration tests against an LDAP server: This section is for gem maintainers to cut a new version of the gem. +* Check out a new branch `release-VERSION` * Update lib/net/ldap/version.rb to next version number X.X.X following {semver}(http://semver.org/). * Update `History.rdoc`. Get latest changes with `script/changelog` - -* On the master branch, run `script/release` +* Open a pull request with these changes for review +* After merging, on the master branch, run `script/release` :include: Contributors.rdoc From 1ac5805e58cb05ac17dfa455102e002448532f0c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 10:44:33 -0700 Subject: [PATCH 362/435] readme extensions section --- README.rdoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.rdoc b/README.rdoc index 89b2d7d7..c3973305 100644 --- a/README.rdoc +++ b/README.rdoc @@ -37,6 +37,14 @@ sources. Simply require either 'net-ldap' or 'net/ldap'. +== Extensions + +This library focuses on the core LDAP RFCs referenced in the description. +However, we recognize there are commonly used extensions to the spec that are +useful. If there is another library which handles it, we list it here. + +* {resolv-srv}[https://rubygems.org/gems/resolv-srv]: Support RFC2782 SRV record lookup and failover + == Develop This task will run the test suite and the From 98d122d3f94707e2367da8353ee2610ec095ff7c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 17:42:23 -0700 Subject: [PATCH 363/435] follow semver --- lib/net/ldap/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 1d0f6b08..219b4156 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.12" + VERSION = "0.12.0" end end From 777438da6cf28581ef7c05703c09855f062f1574 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 18 Sep 2015 17:43:01 -0700 Subject: [PATCH 364/435] missed a spot --- History.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index 70e92eee..40b45255 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,4 +1,4 @@ -=== Net::LDAP 0.12 +=== Net::LDAP 0.12.0 * Correctly set BerIdentifiedString values to UTF-8 {#212}[https://github.com/ruby-ldap/ruby-net-ldap/pull/212] * Raise Net::LDAP::ConnectionRefusedError when new connection is refused. {#213}[https://github.com/ruby-ldap/ruby-net-ldap/pull/213] From f950eca64ef2b73c5219ed830c6749c689046032 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Mon, 21 Sep 2015 23:10:38 +0900 Subject: [PATCH 365/435] Specify the port of LDAP server by giving INTEGRATION_PORT environment variable --- test/test_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 640b0e23..cd34017c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -56,7 +56,7 @@ def setup @service = MockInstrumentationService.new @ldap = Net::LDAP.new \ host: ENV.fetch('INTEGRATION_HOST', 'localhost'), - port: 389, + port: ENV.fetch('INTEGRATION_PORT', 389), admin_user: 'uid=admin,dc=rubyldap,dc=com', admin_password: 'passworD1', search_domains: %w(dc=rubyldap,dc=com), From cede61d2391b2e3746e18c0b0c0d963c5d01e02d Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Sun, 27 Sep 2015 22:00:50 -0500 Subject: [PATCH 366/435] Add the ability to provide a list of hosts to use when opening a connection --- lib/net/ldap.rb | 5 +++ lib/net/ldap/connection.rb | 68 ++++++++++++++++++++++++++---------- test/test_ldap_connection.rb | 38 ++++++++++++++++++++ 3 files changed, 93 insertions(+), 18 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 635aa97d..ffb48719 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -432,6 +432,7 @@ def self.result2string(code) #:nodoc: attr_accessor :host attr_accessor :port + attr_accessor :hosts attr_accessor :base # Instantiate an object of type Net::LDAP to perform directory operations. @@ -440,6 +441,8 @@ def self.result2string(code) #:nodoc: # described below. The following arguments are supported: # * :host => the LDAP server's IP-address (default 127.0.0.1) # * :port => the LDAP server's TCP port (default 389) + # * :hosts => an enumerable of pairs of hosts and corresponding ports with + # which to attempt opening connections (default [[host, port]]) # * :auth => a Hash containing authorization parameters. Currently # supported values include: {:method => :anonymous} and {:method => # :simple, :username => your_user_name, :password => your_password } @@ -468,6 +471,7 @@ def self.result2string(code) #:nodoc: def initialize(args = {}) @host = args[:host] || DefaultHost @port = args[:port] || DefaultPort + @hosts = args[:hosts] @verbose = false # Make this configurable with a switch on the class. @auth = args[:auth] || DefaultAuth @base = args[:base] || DefaultTreebase @@ -1230,6 +1234,7 @@ def new_connection Net::LDAP::Connection.new \ :host => @host, :port => @port, + :hosts => @hosts, :encryption => @encryption, :instrumentation_service => @instrumentation_service end diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 8e0e8c18..05aedfef 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -8,24 +8,56 @@ class Net::LDAP::Connection #:nodoc: def initialize(server) @instrumentation_service = server[:instrumentation_service] + server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil? + if server[:socket] + prepare_socket(server) + else + open_connection(server) + end + + yield self if block_given? + end + + def prepare_socket(server) + @conn = server[:socket] + + if server[:encryption] + setup_encryption server[:encryption] + end + end + + def open_connection(server) + errors = [] + server[:hosts].each do |host, port| + begin + return connect_to_host(host, port, server) + rescue Net::LDAP::Error + errors << $! + end + end + + raise errors.first if errors.size == 1 + raise Net::LDAP::Error, + "Unable to connect to any given server: \n #{errors.join("\n ")}" + end + + def connect_to_host(host, port, server) begin - @conn = server[:socket] || TCPSocket.new(server[:host], server[:port]) + @conn = TCPSocket.new(host, port) rescue SocketError raise Net::LDAP::Error, "No such address or other socket error." rescue Errno::ECONNREFUSED - raise Net::LDAP::ConnectionRefusedError, "Server #{server[:host]} refused connection on port #{server[:port]}." + raise Net::LDAP::ConnectionRefusedError, "Server #{host} refused connection on port #{port}." rescue Errno::EHOSTUNREACH => error - raise Net::LDAP::Error, "Host #{server[:host]} was unreachable (#{error.message})" + raise Net::LDAP::Error, "Host #{host} was unreachable (#{error.message})" rescue Errno::ETIMEDOUT - raise Net::LDAP::Error, "Connection to #{server[:host]} timed out." + raise Net::LDAP::Error, "Connection to #{host} timed out." end if server[:encryption] setup_encryption server[:encryption] end - - yield self if block_given? end module GetbyteForSSLSocket @@ -63,18 +95,18 @@ def self.wrap_with_ssl(io, tls_options = {}) end #-- - # Helper method called only from new, and only after we have a - # successfully-opened @conn instance variable, which is a TCP connection. - # Depending on the received arguments, we establish SSL, potentially - # replacing the value of @conn accordingly. Don't generate any errors here - # if no encryption is requested. DO raise Net::LDAP::Error objects if encryption - # is requested and we have trouble setting it up. That includes if OpenSSL - # is not set up on the machine. (Question: how does the Ruby OpenSSL - # wrapper react in that case?) DO NOT filter exceptions raised by the - # OpenSSL library. Let them pass back to the user. That should make it - # easier for us to debug the problem reports. Presumably (hopefully?) that - # will also produce recognizable errors if someone tries to use this on a - # machine without OpenSSL. + # Helper method called only from prepare_socket or open_connection, and only + # after we have a successfully-opened @conn instance variable, which is a TCP + # connection. Depending on the received arguments, we establish SSL, + # potentially replacing the value of @conn accordingly. Don't generate any + # errors here if no encryption is requested. DO raise Net::LDAP::Error objects + # if encryption is requested and we have trouble setting it up. That includes + # if OpenSSL is not set up on the machine. (Question: how does the Ruby + # OpenSSL wrapper react in that case?) DO NOT filter exceptions raised by the + # OpenSSL library. Let them pass back to the user. That should make it easier + # for us to debug the problem reports. Presumably (hopefully?) that will also + # produce recognizable errors if someone tries to use this on a machine + # without OpenSSL. # # The simple_tls method is intended as the simplest, stupidest, easiest # solution for people who want nothing more than encrypted comms with the diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 4fa7b22d..6fdf0b0a 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -9,6 +9,44 @@ def capture_stderr $stderr = stderr end + def test_list_of_hosts_with_first_host_successful + hosts = [ + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil) + flexmock(TCPSocket).should_receive(:new).ordered.never + Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + end + + def test_list_of_hosts_with_first_host_failure + hosts = [ + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil) + flexmock(TCPSocket).should_receive(:new).ordered.never + Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + end + + def test_list_of_hosts_with_all_hosts_failure + hosts = [ + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError) + flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) + flexmock(TCPSocket).should_receive(:new).ordered.never + assert_raise Net::LDAP::Error do + Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + end + end + def test_unresponsive_host assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) From c0db1d17d4b29da18cc77540177f41c265ad18d0 Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Mon, 28 Sep 2015 18:13:44 -0500 Subject: [PATCH 367/435] Remove enumerable enforcement attempt in tests --- test/test_ldap_connection.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 6fdf0b0a..e5104838 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -17,7 +17,7 @@ def test_list_of_hosts_with_first_host_successful ] flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil) flexmock(TCPSocket).should_receive(:new).ordered.never - Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + Net::LDAP::Connection.new(:hosts => hosts) end def test_list_of_hosts_with_first_host_failure @@ -29,7 +29,7 @@ def test_list_of_hosts_with_first_host_failure flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil) flexmock(TCPSocket).should_receive(:new).ordered.never - Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + Net::LDAP::Connection.new(:hosts => hosts) end def test_list_of_hosts_with_all_hosts_failure @@ -43,7 +43,7 @@ def test_list_of_hosts_with_all_hosts_failure flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.never assert_raise Net::LDAP::Error do - Net::LDAP::Connection.new(:hosts => hosts.to_enum(:each)) + Net::LDAP::Connection.new(:hosts => hosts) end end From 07b48d3c7237fdb36b30ed145afbcf2061a5292c Mon Sep 17 00:00:00 2001 From: ronan lanore Date: Tue, 29 Sep 2015 13:16:01 +0200 Subject: [PATCH 368/435] add slash to attyirbute value filter --- lib/net/ldap/filter.rb | 2 +- test/test_filter_parser.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 0ab847b8..aad84f83 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -752,7 +752,7 @@ def parse_filter_branch(scanner) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) - if value = scanner.scan(/(?:[-\[\]{}\w*.+:@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) + if value = scanner.scan(/(?:[-\[\]{}\w*.+\/:@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) # 20100313 AZ: Assumes that "(uid=george*)" is the same as # "(uid=george* )". The standard doesn't specify, but I can find # no examples that suggest otherwise. diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 210e0218..6f1ca48b 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -14,6 +14,10 @@ def test_brackets assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=[{something}])") end + def test_slash + assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(departmentNumber=FOO//BAR/FOO)") + end + def test_colons 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)") end From 197d46051b68d8fe7aea77082b188f45e7e3c144 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 14:55:41 +0900 Subject: [PATCH 369/435] Extract Simple method as AuthAdapter --- lib/net/ldap/auth_adapter.rb | 25 ++++++++++++++++++ lib/net/ldap/auth_adapters/anon.rb | 3 +++ lib/net/ldap/auth_adapters/anonymous.rb | 3 +++ lib/net/ldap/auth_adapters/simple.rb | 34 +++++++++++++++++++++++++ lib/net/ldap/connection.rb | 21 ++++++++------- 5 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 lib/net/ldap/auth_adapter.rb create mode 100644 lib/net/ldap/auth_adapters/anon.rb create mode 100644 lib/net/ldap/auth_adapters/anonymous.rb create mode 100644 lib/net/ldap/auth_adapters/simple.rb diff --git a/lib/net/ldap/auth_adapter.rb b/lib/net/ldap/auth_adapter.rb new file mode 100644 index 00000000..1ec74360 --- /dev/null +++ b/lib/net/ldap/auth_adapter.rb @@ -0,0 +1,25 @@ +module Net + class LDAP + class AuthAdapter + def self.regiseter(names, adapter) + names = Array(names) + @adapters ||= {} + names.each do |name| + @adapters[name] = adapter + end + end + + def self.[](name) + @adapters[name] + end + + def initialize(conn) + @connection = conn + end + + def bind + raise "bind method must be overwritten" + end + end + end +end diff --git a/lib/net/ldap/auth_adapters/anon.rb b/lib/net/ldap/auth_adapters/anon.rb new file mode 100644 index 00000000..7cb65cb6 --- /dev/null +++ b/lib/net/ldap/auth_adapters/anon.rb @@ -0,0 +1,3 @@ +require 'net/ldap/auth_adapters/simple' + +Net::LDAP::AuthAdapter.register(:anon, Net::LDAP::AuthAdapters::Simple) diff --git a/lib/net/ldap/auth_adapters/anonymous.rb b/lib/net/ldap/auth_adapters/anonymous.rb new file mode 100644 index 00000000..8ed42298 --- /dev/null +++ b/lib/net/ldap/auth_adapters/anonymous.rb @@ -0,0 +1,3 @@ +require 'net/ldap/auth_adapters/simple' + +Net::LDAP::AuthAdapter.register(:anonymous, Net::LDAP::AuthAdapters::Simple) diff --git a/lib/net/ldap/auth_adapters/simple.rb b/lib/net/ldap/auth_adapters/simple.rb new file mode 100644 index 00000000..36e9e174 --- /dev/null +++ b/lib/net/ldap/auth_adapters/simple.rb @@ -0,0 +1,34 @@ +module Net + class LDAP + module AuthAdapters + class Simple < AuthAdapter + def bind(auth) + user, psw = if auth[:method] == :simple + [auth[:username] || auth[:dn], auth[:password]] + else + ["", ""] + end + + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) + + message_id = @connection.next_msgid + request = [ + LdapVersion.to_ber, user.to_ber, + psw.to_ber_contextspecific(0) + ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) + + @connection.write(request, nil, message_id) + pdu = @connection.queued_read(message_id) + + if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult + raise Net::LDAP::NoBindResultError, "no bind result" + end + + pdu + end + end + end + end +end + +Net::LDAP::AuthAdapter.register(:simple, Net::LDAP::AuthAdapters::Simple) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 05aedfef..da53a0b1 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -250,15 +250,18 @@ def next_msgid def bind(auth) instrument "bind.net_ldap_connection" do |payload| payload[:method] = meth = auth[:method] - if [:simple, :anonymous, :anon].include?(meth) - bind_simple auth - elsif meth == :sasl - bind_sasl(auth) - elsif meth == :gss_spnego - bind_gss_spnego(auth) - else - raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})" - end + require "net/ldap/auth_adapters/#{meth}" + adapter = Net::LDAP::AuthAdapterp[meth] + adapter.bind(auth) + # if [:simple, :anonymous, :anon].include?(meth) + # bind_simple auth + # elsif meth == :sasl + # bind_sasl(auth) + # elsif meth == :gss_spnego + # bind_gss_spnego(auth) + # else + # raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})" + # end end end From b57a283c7b87a7a4a07bcf909c03bab32eb1715a Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 14:59:35 +0900 Subject: [PATCH 370/435] Fix uninitialized constant error by adding require statement --- lib/net/ldap/auth_adapters/simple.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap/auth_adapters/simple.rb b/lib/net/ldap/auth_adapters/simple.rb index 36e9e174..2c7301d8 100644 --- a/lib/net/ldap/auth_adapters/simple.rb +++ b/lib/net/ldap/auth_adapters/simple.rb @@ -1,3 +1,5 @@ +require 'net/ldap/auth_adapter' + module Net class LDAP module AuthAdapters From 9c7b1af6b62e609b137371882d41dd4c8e2e9cfd Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 15:02:09 +0900 Subject: [PATCH 371/435] Fix typo --- lib/net/ldap/auth_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/auth_adapter.rb b/lib/net/ldap/auth_adapter.rb index 1ec74360..bd818dec 100644 --- a/lib/net/ldap/auth_adapter.rb +++ b/lib/net/ldap/auth_adapter.rb @@ -1,7 +1,7 @@ module Net class LDAP class AuthAdapter - def self.regiseter(names, adapter) + def self.register(names, adapter) names = Array(names) @adapters ||= {} names.each do |name| From 2546e35c9d6bd661ade33e4b3ad3edd2c57dba66 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 19:42:41 +0900 Subject: [PATCH 372/435] Instantiate AuthAdapter in #bind --- lib/net/ldap/connection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index da53a0b1..29f96d8b 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -251,8 +251,8 @@ def bind(auth) instrument "bind.net_ldap_connection" do |payload| payload[:method] = meth = auth[:method] require "net/ldap/auth_adapters/#{meth}" - adapter = Net::LDAP::AuthAdapterp[meth] - adapter.bind(auth) + adapter = Net::LDAP::AuthAdapter[meth] + adapter.new(self).bind(auth) # if [:simple, :anonymous, :anon].include?(meth) # bind_simple auth # elsif meth == :sasl From 069ad98b12bbc33006249d6edbb5f71542fc015c Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 19:44:47 +0900 Subject: [PATCH 373/435] Fix wrong reference to constant --- lib/net/ldap/auth_adapters/simple.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/auth_adapters/simple.rb b/lib/net/ldap/auth_adapters/simple.rb index 2c7301d8..ade93682 100644 --- a/lib/net/ldap/auth_adapters/simple.rb +++ b/lib/net/ldap/auth_adapters/simple.rb @@ -15,7 +15,7 @@ def bind(auth) message_id = @connection.next_msgid request = [ - LdapVersion.to_ber, user.to_ber, + Net::LDAP::Connection::LdapVersion.to_ber, user.to_ber, psw.to_ber_contextspecific(0) ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) From 585ae827283fc655970579d924368b9dd6f68914 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 2 Oct 2015 19:45:16 +0900 Subject: [PATCH 374/435] Call connection#write method with send --- lib/net/ldap/auth_adapters/simple.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/auth_adapters/simple.rb b/lib/net/ldap/auth_adapters/simple.rb index ade93682..c580cf99 100644 --- a/lib/net/ldap/auth_adapters/simple.rb +++ b/lib/net/ldap/auth_adapters/simple.rb @@ -19,7 +19,7 @@ def bind(auth) psw.to_ber_contextspecific(0) ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) - @connection.write(request, nil, message_id) + @connection.send(:write, request, nil, message_id) pdu = @connection.queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult From ac729dd8c0d748ef4de10a18b78e79197110e39f Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 3 Oct 2015 00:41:25 +0900 Subject: [PATCH 375/435] Net::LDAP::Connection#bind is abolihsed --- lib/net/ldap/connection.rb | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 29f96d8b..802e3832 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -265,35 +265,6 @@ def bind(auth) end end - #-- - # Implements a simple user/psw authentication. Accessed by calling #bind - # with a method of :simple or :anonymous. - #++ - def bind_simple(auth) - user, psw = if auth[:method] == :simple - [auth[:username] || auth[:dn], auth[:password]] - else - ["", ""] - end - - raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) - - 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) - - if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::NoBindResultError, "no bind result" - end - - pdu - end - #-- # Required parameters: :mechanism, :initial_credential and # :challenge_response From d5f7516e0d8061bd97bf7c2cf112fd5912744c73 Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Mon, 28 Sep 2015 10:35:32 -0500 Subject: [PATCH 376/435] DRY up connection handling logic --- lib/net/ldap/connection.rb | 56 ++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 05aedfef..fdec64b5 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -8,56 +8,54 @@ class Net::LDAP::Connection #:nodoc: def initialize(server) @instrumentation_service = server[:instrumentation_service] - server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil? if server[:socket] prepare_socket(server) else + server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil? open_connection(server) end yield self if block_given? end - def prepare_socket(server) - @conn = server[:socket] + def prepare_socket(server, close = false) + socket = server[:socket] + encryption = server[:encryption] - if server[:encryption] - setup_encryption server[:encryption] - end + @conn = socket + setup_encryption encryption if encryption + rescue + # Ensure the connection is closed when requested in the event of an SSL + # setup failure. + @conn.close if close + @conn = nil + raise end def open_connection(server) + hosts = server[:hosts] + encryption = server[:encryption] + errors = [] - server[:hosts].each do |host, port| + hosts.each do |host, port| begin - return connect_to_host(host, port, server) - rescue Net::LDAP::Error - errors << $! + prepare_socket(server.merge(socket: TCPSocket.new(host, port)), true) + return + rescue Net::LDAP::Error, SocketError, SystemCallError, + OpenSSL::SSL::SSLError + errors << [$!, host, port] end end - raise errors.first if errors.size == 1 - raise Net::LDAP::Error, - "Unable to connect to any given server: \n #{errors.join("\n ")}" - end - - def connect_to_host(host, port, server) - begin - @conn = TCPSocket.new(host, port) - rescue SocketError - raise Net::LDAP::Error, "No such address or other socket error." - rescue Errno::ECONNREFUSED - raise Net::LDAP::ConnectionRefusedError, "Server #{host} refused connection on port #{port}." - rescue Errno::EHOSTUNREACH => error - raise Net::LDAP::Error, "Host #{host} was unreachable (#{error.message})" - rescue Errno::ETIMEDOUT - raise Net::LDAP::Error, "Connection to #{host} timed out." + if errors.size == 1 + error = errors.first.first + raise Net::LDAP::ConnectionRefusedError, error.message if error.kind_of? Errno::ECONNREFUSED + raise Net::LDAP::Error, error.message end - if server[:encryption] - setup_encryption server[:encryption] - end + raise Net::LDAP::Error, + "Unable to connect to any given server: \n #{errors.map { |e, h, p| "#{e.class}: #{e.message} (#{h}:#{p})" }.join("\n ")}" end module GetbyteForSSLSocket From 91db1ba20ef4b31f5e0516b293f7fd29089b22c9 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 3 Oct 2015 16:38:01 +0900 Subject: [PATCH 377/435] Define Sasl AuthAdapter --- lib/net/ldap/auth_adapters/sasl.rb | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 lib/net/ldap/auth_adapters/sasl.rb diff --git a/lib/net/ldap/auth_adapters/sasl.rb b/lib/net/ldap/auth_adapters/sasl.rb new file mode 100644 index 00000000..01e7f05a --- /dev/null +++ b/lib/net/ldap/auth_adapters/sasl.rb @@ -0,0 +1,41 @@ +require 'net/ldap/auth_adapter' + +module Net + class LDAP + module AuthAdapters + class Sasl < Net::LDAP::AuthAdapter + def bind(auth) + mech, cred, chall = auth[:mechanism], auth[:initial_credential], + auth[:challenge_response] + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall) + + message_id = @connection.next_msgid + + n = 0 + loop { + sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) + request = [ + Net::LDAP::Connection::LdapVersion.to_ber, "".to_ber, sasl + ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) + + @connection.send(:write, request, nil, message_id) + pdu = @connection.queued_read(message_id) + + if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult + raise Net::LDAP::NoBindResultError, "no bind result" + end + + return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress + raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + + cred = chall.call(pdu.result_server_sasl_creds) + } + + raise Net::LDAP::SASLChallengeOverflowError, "why are we here?" + end + end + end + end +end + +Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapters::Sasl) From ab20ad22cede28a689b47502628fd83a8bb1ba86 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 3 Oct 2015 22:17:20 +0900 Subject: [PATCH 378/435] Define GSS_SPNEGO AuthAdapter --- lib/net/ldap/auth_adapters/gss_spnego.rb | 42 +++++++++++ lib/net/ldap/auth_adapters/sasl.rb | 21 ++++++ lib/net/ldap/connection.rb | 92 ------------------------ 3 files changed, 63 insertions(+), 92 deletions(-) create mode 100644 lib/net/ldap/auth_adapters/gss_spnego.rb diff --git a/lib/net/ldap/auth_adapters/gss_spnego.rb b/lib/net/ldap/auth_adapters/gss_spnego.rb new file mode 100644 index 00000000..2513f150 --- /dev/null +++ b/lib/net/ldap/auth_adapters/gss_spnego.rb @@ -0,0 +1,42 @@ +require 'net/ldap/auth_adapter' +require 'net/ldap/auth_adapters/sasl' + +module Net + class LDAP + module AuthAdapers + #-- + # PROVISIONAL, only for testing SASL implementations. DON'T USE THIS YET. + # Uses Kohei Kajimoto's Ruby/NTLM. We have to find a clean way to + # integrate it without introducing an external dependency. + # + # This authentication method is accessed by calling #bind with a :method + # parameter of :gss_spnego. It requires :username and :password + # attributes, just like the :simple authentication method. It performs a + # GSS-SPNEGO authentication with the server, which is presumed to be a + # Microsoft Active Directory. + #++ + class GSS_SPNEGO < Net::LDAP::AuthAdapter + def bind(auth) + require 'ntlm' + + user, psw = [auth[:username] || auth[:dn], auth[:password]] + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) + + nego = proc { |challenge| + t2_msg = NTLM::Message.parse(challenge) + t3_msg = t2_msg.response({ :user => user, :password => psw }, + { :ntlmv2 => true }) + t3_msg.serialize + } + + Net::LDAP::AuthAdapter.new(@connection). + bind(:method => :sasl, :mechanism => "GSS-SPNEGO", + :initial_credential => NTLM::Message::Type1.new.serialize, + :challenge_response => nego) + end + end + end + end +end + +Net::LDAP::Adapter.register(:gss_spnego, Net::LDAP::AuthAdapters::GSS_SPNEGO) diff --git a/lib/net/ldap/auth_adapters/sasl.rb b/lib/net/ldap/auth_adapters/sasl.rb index 01e7f05a..c7c460c0 100644 --- a/lib/net/ldap/auth_adapters/sasl.rb +++ b/lib/net/ldap/auth_adapters/sasl.rb @@ -4,6 +4,27 @@ module Net class LDAP module AuthAdapters class Sasl < Net::LDAP::AuthAdapter + #-- + # Required parameters: :mechanism, :initial_credential and + # :challenge_response + # + # Mechanism is a string value that will be passed in the SASL-packet's + # "mechanism" field. + # + # Initial credential is most likely a string. It's passed in the initial + # BindRequest that goes to the server. In some protocols, it may be empty. + # + # Challenge-response is a Ruby proc that takes a single parameter and + # returns an object that will typically be a string. The + # challenge-response block is called when the server returns a + # BindResponse with a result code of 14 (saslBindInProgress). The + # challenge-response block receives a parameter containing the data + # returned by the server in the saslServerCreds field of the LDAP + # BindResponse packet. The challenge-response block may be called multiple + # times during the course of a SASL authentication, and each time it must + # return a value that will be passed back to the server as the credential + # data in the next BindRequest packet. + #++ def bind(auth) mech, cred, chall = auth[:mechanism], auth[:initial_credential], auth[:challenge_response] diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 802e3832..e3129348 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -253,101 +253,9 @@ def bind(auth) require "net/ldap/auth_adapters/#{meth}" adapter = Net::LDAP::AuthAdapter[meth] adapter.new(self).bind(auth) - # if [:simple, :anonymous, :anon].include?(meth) - # bind_simple auth - # elsif meth == :sasl - # bind_sasl(auth) - # elsif meth == :gss_spnego - # bind_gss_spnego(auth) - # else - # raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})" - # end end end - #-- - # Required parameters: :mechanism, :initial_credential and - # :challenge_response - # - # Mechanism is a string value that will be passed in the SASL-packet's - # "mechanism" field. - # - # Initial credential is most likely a string. It's passed in the initial - # BindRequest that goes to the server. In some protocols, it may be empty. - # - # Challenge-response is a Ruby proc that takes a single parameter and - # returns an object that will typically be a string. The - # challenge-response block is called when the server returns a - # BindResponse with a result code of 14 (saslBindInProgress). The - # challenge-response block receives a parameter containing the data - # returned by the server in the saslServerCreds field of the LDAP - # BindResponse packet. The challenge-response block may be called multiple - # times during the course of a SASL authentication, and each time it must - # return a value that will be passed back to the server as the credential - # data in the next BindRequest packet. - #++ - def bind_sasl(auth) - mech, cred, chall = auth[:mechanism], auth[:initial_credential], - auth[:challenge_response] - raise Net::LDAP::BindingInformationInvalidError, "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, nil, message_id) - pdu = queued_read(message_id) - - if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult - raise Net::LDAP::NoBindResultError, "no bind result" - end - - return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress - raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) - - cred = chall.call(pdu.result_server_sasl_creds) - } - - raise Net::LDAP::SASLChallengeOverflowError, "why are we here?" - end - private :bind_sasl - - #-- - # PROVISIONAL, only for testing SASL implementations. DON'T USE THIS YET. - # Uses Kohei Kajimoto's Ruby/NTLM. We have to find a clean way to - # integrate it without introducing an external dependency. - # - # This authentication method is accessed by calling #bind with a :method - # parameter of :gss_spnego. It requires :username and :password - # attributes, just like the :simple authentication method. It performs a - # GSS-SPNEGO authentication with the server, which is presumed to be a - # Microsoft Active Directory. - #++ - def bind_gss_spnego(auth) - require 'ntlm' - - user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) - - nego = proc { |challenge| - t2_msg = NTLM::Message.parse(challenge) - t3_msg = t2_msg.response({ :user => user, :password => psw }, - { :ntlmv2 => true }) - t3_msg.serialize - } - - bind_sasl(:method => :sasl, :mechanism => "GSS-SPNEGO", - :initial_credential => NTLM::Message::Type1.new.serialize, - :challenge_response => nego) - end - private :bind_gss_spnego - - #-- # Allow the caller to specify a sort control # From 60edf55bacd355b4c742c6f56137fa89467bcff6 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Oct 2015 20:21:44 +0900 Subject: [PATCH 379/435] Make namespace of AuthAdapater singular --- lib/net/ldap/{auth_adapters => auth_adapter}/gss_spnego.rb | 2 +- lib/net/ldap/{auth_adapters => auth_adapter}/sasl.rb | 2 +- lib/net/ldap/{auth_adapters => auth_adapter}/simple.rb | 2 +- lib/net/ldap/auth_adapters/anon.rb | 3 --- lib/net/ldap/auth_adapters/anonymous.rb | 3 --- 5 files changed, 3 insertions(+), 9 deletions(-) rename lib/net/ldap/{auth_adapters => auth_adapter}/gss_spnego.rb (97%) rename lib/net/ldap/{auth_adapters => auth_adapter}/sasl.rb (99%) rename lib/net/ldap/{auth_adapters => auth_adapter}/simple.rb (97%) delete mode 100644 lib/net/ldap/auth_adapters/anon.rb delete mode 100644 lib/net/ldap/auth_adapters/anonymous.rb diff --git a/lib/net/ldap/auth_adapters/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb similarity index 97% rename from lib/net/ldap/auth_adapters/gss_spnego.rb rename to lib/net/ldap/auth_adapter/gss_spnego.rb index 2513f150..b44b5c5e 100644 --- a/lib/net/ldap/auth_adapters/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -1,5 +1,5 @@ require 'net/ldap/auth_adapter' -require 'net/ldap/auth_adapters/sasl' +require 'net/ldap/auth_adapter/sasl' module Net class LDAP diff --git a/lib/net/ldap/auth_adapters/sasl.rb b/lib/net/ldap/auth_adapter/sasl.rb similarity index 99% rename from lib/net/ldap/auth_adapters/sasl.rb rename to lib/net/ldap/auth_adapter/sasl.rb index c7c460c0..38e977b9 100644 --- a/lib/net/ldap/auth_adapters/sasl.rb +++ b/lib/net/ldap/auth_adapter/sasl.rb @@ -2,7 +2,7 @@ module Net class LDAP - module AuthAdapters + module AuthAdapter class Sasl < Net::LDAP::AuthAdapter #-- # Required parameters: :mechanism, :initial_credential and diff --git a/lib/net/ldap/auth_adapters/simple.rb b/lib/net/ldap/auth_adapter/simple.rb similarity index 97% rename from lib/net/ldap/auth_adapters/simple.rb rename to lib/net/ldap/auth_adapter/simple.rb index c580cf99..471878c5 100644 --- a/lib/net/ldap/auth_adapters/simple.rb +++ b/lib/net/ldap/auth_adapter/simple.rb @@ -2,7 +2,7 @@ module Net class LDAP - module AuthAdapters + class AuthAdapter class Simple < AuthAdapter def bind(auth) user, psw = if auth[:method] == :simple diff --git a/lib/net/ldap/auth_adapters/anon.rb b/lib/net/ldap/auth_adapters/anon.rb deleted file mode 100644 index 7cb65cb6..00000000 --- a/lib/net/ldap/auth_adapters/anon.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'net/ldap/auth_adapters/simple' - -Net::LDAP::AuthAdapter.register(:anon, Net::LDAP::AuthAdapters::Simple) diff --git a/lib/net/ldap/auth_adapters/anonymous.rb b/lib/net/ldap/auth_adapters/anonymous.rb deleted file mode 100644 index 8ed42298..00000000 --- a/lib/net/ldap/auth_adapters/anonymous.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'net/ldap/auth_adapters/simple' - -Net::LDAP::AuthAdapter.register(:anonymous, Net::LDAP::AuthAdapters::Simple) From b56450d0ae75e94da14803057c0b4aa35dfdbbad Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Oct 2015 20:27:16 +0900 Subject: [PATCH 380/435] Fix wrong adapter used in GSS_SPNEGO --- lib/net/ldap/auth_adapter/gss_spnego.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index b44b5c5e..5eb62a0a 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -29,7 +29,7 @@ def bind(auth) t3_msg.serialize } - Net::LDAP::AuthAdapter.new(@connection). + Net::LDAP::AuthAdapter::Sasl.new(@connection). bind(:method => :sasl, :mechanism => "GSS-SPNEGO", :initial_credential => NTLM::Message::Type1.new.serialize, :challenge_response => nego) From 86e4ba16fe9177bd3fce308616ef2258f4ad4d34 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 7 Oct 2015 20:39:31 +0900 Subject: [PATCH 381/435] Move registration of AuthAdapters to net/ldap --- lib/net/ldap.rb | 6 ++++++ lib/net/ldap/auth_adapter/gss_spnego.rb | 2 -- lib/net/ldap/auth_adapter/sasl.rb | 4 +--- lib/net/ldap/auth_adapter/simple.rb | 2 -- lib/net/ldap/connection.rb | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index ffb48719..7c151895 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -27,6 +27,12 @@ class LDAP require 'net/ldap/connection' require 'net/ldap/version' require 'net/ldap/error' +require 'net/ldap/auth_adapter' +require 'net/ldap/auth_adapter/simple' +require 'net/ldap/auth_adapter/sasl' + +Net::LDAP::AuthAdapter.register([:simple, :anon, :anonymous], Net::LDAP::AuthAdapter::Simple) +Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapter::Sasl) # == Quick-start for the Impatient # === Quick Example of a user-authentication against an LDAP directory: diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index 5eb62a0a..e251f038 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -38,5 +38,3 @@ def bind(auth) end end end - -Net::LDAP::Adapter.register(:gss_spnego, Net::LDAP::AuthAdapters::GSS_SPNEGO) diff --git a/lib/net/ldap/auth_adapter/sasl.rb b/lib/net/ldap/auth_adapter/sasl.rb index 38e977b9..fa7315b5 100644 --- a/lib/net/ldap/auth_adapter/sasl.rb +++ b/lib/net/ldap/auth_adapter/sasl.rb @@ -2,7 +2,7 @@ module Net class LDAP - module AuthAdapter + class AuthAdapter class Sasl < Net::LDAP::AuthAdapter #-- # Required parameters: :mechanism, :initial_credential and @@ -58,5 +58,3 @@ def bind(auth) end end end - -Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapters::Sasl) diff --git a/lib/net/ldap/auth_adapter/simple.rb b/lib/net/ldap/auth_adapter/simple.rb index 471878c5..d01b57ae 100644 --- a/lib/net/ldap/auth_adapter/simple.rb +++ b/lib/net/ldap/auth_adapter/simple.rb @@ -32,5 +32,3 @@ def bind(auth) end end end - -Net::LDAP::AuthAdapter.register(:simple, Net::LDAP::AuthAdapters::Simple) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e3129348..f45e54a0 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -250,7 +250,6 @@ def next_msgid def bind(auth) instrument "bind.net_ldap_connection" do |payload| payload[:method] = meth = auth[:method] - require "net/ldap/auth_adapters/#{meth}" adapter = Net::LDAP::AuthAdapter[meth] adapter.new(self).bind(auth) end From fbb1951f41bfe42599bfe691dc276e45f09856d1 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 9 Oct 2015 05:00:07 +0900 Subject: [PATCH 382/435] Register gss_spnego when requiring 'net/ldap' --- lib/net/ldap.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 7c151895..2467663d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -30,9 +30,11 @@ class LDAP require 'net/ldap/auth_adapter' require 'net/ldap/auth_adapter/simple' require 'net/ldap/auth_adapter/sasl' +require 'net/ldap/auth_adapter/gss_spnego' Net::LDAP::AuthAdapter.register([:simple, :anon, :anonymous], Net::LDAP::AuthAdapter::Simple) Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapter::Sasl) +Net::LDAP::AuthAdapter.register(:gss_spnego, Net::LDAP::AuthAdapter::Sasl) # == Quick-start for the Impatient # === Quick Example of a user-authentication against an LDAP directory: From 9bf1f3003a5f20c370f8d0dbd0ce88dfdeac1434 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Fri, 9 Oct 2015 05:35:13 +0900 Subject: [PATCH 383/435] Raise exception when specifying undefined auth method --- lib/net/ldap/auth_adapter.rb | 6 +++++- test/test_auth_adapter.rb | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/test_auth_adapter.rb diff --git a/lib/net/ldap/auth_adapter.rb b/lib/net/ldap/auth_adapter.rb index bd818dec..f74232d1 100644 --- a/lib/net/ldap/auth_adapter.rb +++ b/lib/net/ldap/auth_adapter.rb @@ -10,7 +10,11 @@ def self.register(names, adapter) end def self.[](name) - @adapters[name] + a = @adapters[name] + if a.nil? + raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{name})" + end + return a end def initialize(conn) diff --git a/test/test_auth_adapter.rb b/test/test_auth_adapter.rb new file mode 100644 index 00000000..7cec57bc --- /dev/null +++ b/test/test_auth_adapter.rb @@ -0,0 +1,11 @@ +require 'test_helper' + +class TestAuthAdapter < Test::Unit::TestCase + def test_undefined_auth_adapter + flexmock(TCPSocket).should_receive(:new).ordered.with('ldap.example.com', 379).once.and_return(nil) + conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379) + assert_raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (foo)" do + conn.bind(method: :foo) + end + end +end From 8be52247f156fd640b0140bd336f0d1b7be302c7 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sat, 10 Oct 2015 06:52:02 +0900 Subject: [PATCH 384/435] GSS SPNEGO is not supported --- lib/net/ldap.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 2467663d..7c151895 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -30,11 +30,9 @@ class LDAP require 'net/ldap/auth_adapter' require 'net/ldap/auth_adapter/simple' require 'net/ldap/auth_adapter/sasl' -require 'net/ldap/auth_adapter/gss_spnego' Net::LDAP::AuthAdapter.register([:simple, :anon, :anonymous], Net::LDAP::AuthAdapter::Simple) Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapter::Sasl) -Net::LDAP::AuthAdapter.register(:gss_spnego, Net::LDAP::AuthAdapter::Sasl) # == Quick-start for the Impatient # === Quick Example of a user-authentication against an LDAP directory: From edee2ee46b0f3bba2ea5b71019a7a11a53bbb23b Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Sun, 18 Oct 2015 17:32:07 -0500 Subject: [PATCH 385/435] Move connection error handling logic into a new error class * ConnectionError wraps the creation of several error types for backward compatibility * For now, ConnectionError is only created when more than 1 error is given to the constructor * In the future, ConnectionError should be used even in the single error case --- lib/net/ldap/connection.rb | 9 +-------- lib/net/ldap/error.rb | 19 +++++++++++++++++++ test/test_ldap_connection.rb | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index fdec64b5..d28554ff 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -48,14 +48,7 @@ def open_connection(server) end end - if errors.size == 1 - error = errors.first.first - raise Net::LDAP::ConnectionRefusedError, error.message if error.kind_of? Errno::ECONNREFUSED - raise Net::LDAP::Error, error.message - end - - raise Net::LDAP::Error, - "Unable to connect to any given server: \n #{errors.map { |e, h, p| "#{e.class}: #{e.message} (#{h}:#{p})" }.join("\n ")}" + raise Net::LDAP::ConnectionError.new(errors) end module GetbyteForSSLSocket diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index 38b4a4a5..9f157195 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -25,6 +25,25 @@ def warn_deprecation_message warn "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead." end end + class ConnectionError < Error + def self.new(errors) + error = errors.first.first + if errors.size == 1 + if error.kind_of? Errno::ECONNREFUSED + return Net::LDAP::ConnectionRefusedError.new(error.message) + end + + return Net::LDAP::Error.new(error.message) + end + + super + end + + def initialize(errors) + message = "Unable to connect to any given server: \n #{errors.map { |e, h, p| "#{e.class}: #{e.message} (#{h}:#{p})" }.join("\n ")}" + super(message) + end + end class NoOpenSSLError < Error; end class NoStartTLSResultError < Error; end class NoSearchBaseError < Error; end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index e5104838..d991bddc 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -42,7 +42,7 @@ def test_list_of_hosts_with_all_hosts_failure flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.never - assert_raise Net::LDAP::Error do + assert_raise Net::LDAP::ConnectionError do Net::LDAP::Connection.new(:hosts => hosts) end end From e1a0d1348f2e49acb5ba67e803e9102eb1b64f14 Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Sun, 18 Oct 2015 17:38:03 -0500 Subject: [PATCH 386/435] Resolve rubocop violations --- test/test_ldap_connection.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index d991bddc..73752631 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -11,10 +11,10 @@ def capture_stderr def test_list_of_hosts_with_first_host_successful hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], - ] + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil) flexmock(TCPSocket).should_receive(:new).ordered.never Net::LDAP::Connection.new(:hosts => hosts) @@ -22,10 +22,10 @@ def test_list_of_hosts_with_first_host_successful def test_list_of_hosts_with_first_host_failure hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], - ] + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil) flexmock(TCPSocket).should_receive(:new).ordered.never @@ -34,10 +34,10 @@ def test_list_of_hosts_with_first_host_failure def test_list_of_hosts_with_all_hosts_failure hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], - ] + ['test.mocked.com', 636], + ['test2.mocked.com', 636], + ['test3.mocked.com', 636], + ] flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError) flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) From 5a4ddb14a1f1abf54202c8e7fcd5bf3ba287c91f Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Mon, 19 Oct 2015 14:42:08 -0500 Subject: [PATCH 387/435] Assign exceptions to a variable rather than use $! --- lib/net/ldap/connection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index d28554ff..3c3dbfd6 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -43,8 +43,8 @@ def open_connection(server) prepare_socket(server.merge(socket: TCPSocket.new(host, port)), true) return rescue Net::LDAP::Error, SocketError, SystemCallError, - OpenSSL::SSL::SSLError - errors << [$!, host, port] + OpenSSL::SSL::SSLError => e + errors << [e, host, port] end end From ab320af47c6c75536ac6ab7a83a419746132f67a Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Mon, 19 Oct 2015 14:43:38 -0500 Subject: [PATCH 388/435] Close the socket where opened when necessary --- lib/net/ldap/connection.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 3c3dbfd6..f3b42f71 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -19,18 +19,12 @@ def initialize(server) yield self if block_given? end - def prepare_socket(server, close = false) + def prepare_socket(server) socket = server[:socket] encryption = server[:encryption] @conn = socket setup_encryption encryption if encryption - rescue - # Ensure the connection is closed when requested in the event of an SSL - # setup failure. - @conn.close if close - @conn = nil - raise end def open_connection(server) @@ -40,10 +34,14 @@ def open_connection(server) errors = [] hosts.each do |host, port| begin - prepare_socket(server.merge(socket: TCPSocket.new(host, port)), true) + socket = TCPSocket.new(host, port) + prepare_socket(server.merge(socket: socket)) return rescue Net::LDAP::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e + # Ensure the connection is closed in the event a setup failure. + socket.close unless socket.nil? + socket = nil errors << [e, host, port] end end From e8290692cfd9f196c0d90f36fca29bc530e51dfe Mon Sep 17 00:00:00 2001 From: Jeremy Bopp Date: Sun, 25 Oct 2015 22:28:21 -0500 Subject: [PATCH 389/435] Move connection cleanup logic into the close method --- lib/net/ldap/connection.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index f3b42f71..691e284f 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -34,14 +34,12 @@ def open_connection(server) errors = [] hosts.each do |host, port| begin - socket = TCPSocket.new(host, port) - prepare_socket(server.merge(socket: socket)) + prepare_socket(server.merge(socket: TCPSocket.new(host, port))) return rescue Net::LDAP::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e # Ensure the connection is closed in the event a setup failure. - socket.close unless socket.nil? - socket = nil + close errors << [e, host, port] end end @@ -145,6 +143,7 @@ def setup_encryption(args) # have to call it, but perhaps it will come in handy someday. #++ def close + return if @conn.nil? @conn.close @conn = nil end From 762b78f77f394a0efed96a4854a22c464d08ef2f Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 27 Oct 2015 10:48:52 -0600 Subject: [PATCH 390/435] release 0.12.0 --- History.rdoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/History.rdoc b/History.rdoc index 40b45255..1e0270a8 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,5 +1,10 @@ === Net::LDAP 0.12.0 +* DRY up connection handling logic {#224}[https://github.com/ruby-ldap/ruby-net-ldap/pull/224] +* Define auth adapters {#226}[https://github.com/ruby-ldap/ruby-net-ldap/pull/226] +* add slash to attribute value filter {#225}[https://github.com/ruby-ldap/ruby-net-ldap/pull/225] +* Add the ability to provide a list of hosts for a connection {#223}[https://github.com/ruby-ldap/ruby-net-ldap/pull/223] +* Specify the port of LDAP server by giving INTEGRATION_PORT {#221}[https://github.com/ruby-ldap/ruby-net-ldap/pull/221] * Correctly set BerIdentifiedString values to UTF-8 {#212}[https://github.com/ruby-ldap/ruby-net-ldap/pull/212] * Raise Net::LDAP::ConnectionRefusedError when new connection is refused. {#213}[https://github.com/ruby-ldap/ruby-net-ldap/pull/213] * obscure auth password upon #inspect, added test, closes #216 {#217}[https://github.com/ruby-ldap/ruby-net-ldap/pull/217] From 2f053dd12264da42d90144341b4c0f0d8a372349 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 27 Oct 2015 11:28:56 -0600 Subject: [PATCH 391/435] Release 0.12.0 From b637db7efe22e2b864d3e37b21726ab3589188c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20G=C3=BCnnewig?= Date: Thu, 5 Nov 2015 17:32:10 +0100 Subject: [PATCH 392/435] Set operation result if LDAP server is not accessible --- lib/net/ldap.rb | 6 ++++++ test/test_ldap_connection.rb | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 7c151895..0ec7fbb7 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1243,5 +1243,11 @@ def new_connection :hosts => @hosts, :encryption => @encryption, :instrumentation_service => @instrumentation_service + rescue Errno::ECONNREFUSED, Net::LDAP::ConnectionRefusedError => e + @result = { + :resultCode => 52, + :errorMessage => ResultStrings[ResultCodeUnavailable] + } + raise e end end # class LDAP diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 73752631..b4c77615 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -47,6 +47,19 @@ def test_list_of_hosts_with_all_hosts_failure end end + def test_result_for_connection_failed_is_set + flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) + + ldap_client = Net::LDAP.new(host: '127.0.0.1', port: 12345) + + assert_raise Net::LDAP::ConnectionRefusedError do + ldap_client.bind(method: :simple, username: 'asdf', password: 'asdf') + end + + assert_equal(ldap_client.get_operation_result.code, 52) + assert_equal(ldap_client.get_operation_result.message, 'Unavailable') + end + def test_unresponsive_host assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) From 83406ee5ca7f26c0a6580e3ca2d5942b2b3a27a3 Mon Sep 17 00:00:00 2001 From: Justin Ouellette Date: Sun, 8 Nov 2015 21:13:30 -0500 Subject: [PATCH 393/435] Fixed capitalization of StartTLSError --- lib/net/ldap/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4e3f6dd0..71ff7b43 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -130,7 +130,7 @@ def setup_encryption(args) if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn, args[:tls_options]) else - raise Net::LDAP::StartTlSError, "start_tls failed: #{pdu.result_code}" + raise Net::LDAP::StartTLSError, "start_tls failed: #{pdu.result_code}" end else raise Net::LDAP::EncMethodUnsupportedError, "unsupported encryption method #{args[:method]}" From d5e6afd6c77ad7a62d49b57000a650df14d26352 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 9 Nov 2015 22:17:50 -0800 Subject: [PATCH 394/435] lazy init Net::LDAP::Connection's internal sock --- lib/net/ldap/connection.rb | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4e3f6dd0..e987a443 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -6,16 +6,10 @@ class Net::LDAP::Connection #:nodoc: LdapVersion = 3 MaxSaslChallenges = 10 - def initialize(server) + def initialize(server = {}) + @server = server @instrumentation_service = server[:instrumentation_service] - if server[:socket] - prepare_socket(server) - else - server[:hosts] = [[server[:host], server[:port]]] if server[:hosts].nil? - open_connection(server) - end - yield self if block_given? end @@ -195,7 +189,7 @@ def message_queue def read(syntax = Net::LDAP::AsnSyntax) ber_object = instrument "read.net_ldap_connection", :syntax => syntax do |payload| - @conn.read_ber(syntax) do |id, content_length| + socket.read_ber(syntax) do |id, content_length| payload[:object_type_id] = id payload[:content_length] = content_length end @@ -225,7 +219,7 @@ def read(syntax = Net::LDAP::AsnSyntax) def write(request, controls = nil, message_id = next_msgid) instrument "write.net_ldap_connection" do |payload| packet = [message_id.to_ber, request, controls].compact.to_ber_sequence - payload[:content_length] = @conn.write(packet) + payload[:content_length] = socket.write(packet) end end private :write @@ -600,4 +594,18 @@ def delete(args) pdu end + + private + + # Returns a Socket like object used internally to communicate with LDAP server + # + # Typically a TCPSocket, but can be a OpenSSL::SSL::SSLSocket + def socket + return @conn if defined? @conn + + # First refactoring uses the existing methods open_connection and + # prepare_socket to set @conn. Next cleanup would centralize connection + # handling here. + open_connection(@server) + end end # class Connection From 4a415bcc4f43c2f40ed037266089a9405b0d2768 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 9 Nov 2015 23:29:48 -0800 Subject: [PATCH 395/435] preserve existing socket init code --- lib/net/ldap/connection.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e987a443..84164ef7 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -606,6 +606,13 @@ def socket # First refactoring uses the existing methods open_connection and # prepare_socket to set @conn. Next cleanup would centralize connection # handling here. - open_connection(@server) + if @server[:socket] + prepare_socket(@server) + else + @server[:hosts] = [[@server[:host], @server[:port]]] if @server[:hosts].nil? + open_connection(@server) + end + + @conn end end # class Connection From b8568061cf1d55966aa87d75bf8825f1fe3e143e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 9 Nov 2015 23:30:36 -0800 Subject: [PATCH 396/435] #socket internal for easier testing --- lib/net/ldap/connection.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 84164ef7..0d419c4d 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -595,9 +595,8 @@ def delete(args) pdu end - private - - # Returns a Socket like object used internally to communicate with LDAP server + # Internal: Returns a Socket like object used internally to communicate with + # LDAP server. # # Typically a TCPSocket, but can be a OpenSSL::SSL::SSLSocket def socket From 76dde7b25b130e7e847b72700fde593a9ca86024 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 9 Nov 2015 23:30:50 -0800 Subject: [PATCH 397/435] parameterize socket_class for testing --- lib/net/ldap/connection.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 0d419c4d..ef703dd2 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -13,6 +13,15 @@ def initialize(server = {}) yield self if block_given? end + # Allows tests to parameterize what socket class to use + def socket_class + @socket_class || TCPSocket + end + + def socket_class=(socket_class) + @socket_class = socket_class + end + def prepare_socket(server) socket = server[:socket] encryption = server[:encryption] @@ -28,7 +37,7 @@ def open_connection(server) errors = [] hosts.each do |host, port| begin - prepare_socket(server.merge(socket: TCPSocket.new(host, port))) + prepare_socket(server.merge(socket: socket_class.new(host, port))) return rescue Net::LDAP::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e From 53cc6b501e5dbe25ab1498968eafec0a7c927fa9 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Mon, 9 Nov 2015 23:32:12 -0800 Subject: [PATCH 398/435] remove tcpsocket stubbing with FakeTCPSocket class --- test/test_ldap_connection.rb | 54 ++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index b4c77615..c75ad410 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -9,41 +9,53 @@ def capture_stderr $stderr = stderr end + # Fake socket for testing + # + # FakeTCPSocket.new("success", 636) + # FakeTCPSocket.new("fail.SocketError", 636) # raises SocketError + class FakeTCPSocket + def initialize(host, port) + status, error = host.split(".") + if status == "fail" + raise Object.const_get(error) + end + end + end + def test_list_of_hosts_with_first_host_successful hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], + ["success.host", 636], + ["fail.SocketError", 636], + ["fail.SocketError", 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil) - flexmock(TCPSocket).should_receive(:new).ordered.never - Net::LDAP::Connection.new(:hosts => hosts) + + connection = Net::LDAP::Connection.new(:hosts => hosts) + connection.socket_class = FakeTCPSocket + connection.socket end def test_list_of_hosts_with_first_host_failure hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], + ["fail.SocketError", 636], + ["success.host", 636], + ["fail.SocketError", 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil) - flexmock(TCPSocket).should_receive(:new).ordered.never - Net::LDAP::Connection.new(:hosts => hosts) + connection = Net::LDAP::Connection.new(:hosts => hosts) + connection.socket_class = FakeTCPSocket + connection.socket end def test_list_of_hosts_with_all_hosts_failure hosts = [ - ['test.mocked.com', 636], - ['test2.mocked.com', 636], - ['test3.mocked.com', 636], + ["fail.SocketError", 636], + ["fail.SocketError", 636], + ["fail.SocketError", 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.never + + connection = Net::LDAP::Connection.new(:hosts => hosts) + connection.socket_class = FakeTCPSocket assert_raise Net::LDAP::ConnectionError do - Net::LDAP::Connection.new(:hosts => hosts) + connection.socket end end From e9a1bf19603e51cd5b3718e30309f574311037e5 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 10 Nov 2015 00:13:22 -0800 Subject: [PATCH 399/435] add initialize docs --- lib/net/ldap/connection.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index ef703dd2..6d58f6ea 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -6,6 +6,14 @@ class Net::LDAP::Connection #:nodoc: LdapVersion = 3 MaxSaslChallenges = 10 + # Initialize a connection to an LDAP server + # + # :server + # :hosts Array of tuples specifying host, port + # :host host + # :port port + # :socket prepared socket + # def initialize(server = {}) @server = server @instrumentation_service = server[:instrumentation_service] From 9a2e26ef08e0781b6a1ad294c5c073918f2f2384 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 10 Nov 2015 00:30:58 -0800 Subject: [PATCH 400/435] preserve existing behavior --- lib/net/ldap.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 0ec7fbb7..d952c484 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1237,12 +1237,16 @@ def use_connection(args) # Establish a new connection to the LDAP server def new_connection - Net::LDAP::Connection.new \ + connection = Net::LDAP::Connection.new \ :host => @host, :port => @port, :hosts => @hosts, :encryption => @encryption, :instrumentation_service => @instrumentation_service + + # Force connect to see if there's a connection error + connection.socket + connection rescue Errno::ECONNREFUSED, Net::LDAP::ConnectionRefusedError => e @result = { :resultCode => 52, From 259f18af42b56efe3d371ba59e9349dda736d55d Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 10 Nov 2015 00:31:17 -0800 Subject: [PATCH 401/435] update tests --- test/test_ldap_connection.rb | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index c75ad410..a8620eb7 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -59,6 +59,7 @@ def test_list_of_hosts_with_all_hosts_failure end end + # This belongs in test_ldap, not test_ldap_connection def test_result_for_connection_failed_is_set flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) @@ -73,33 +74,36 @@ def test_result_for_connection_failed_is_set end def test_unresponsive_host + connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636) + connection.socket_class = FakeTCPSocket assert_raise Net::LDAP::Error do - Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + connection.socket end end def test_blocked_port - flexmock(TCPSocket).should_receive(:new).and_raise(SocketError) + connection = Net::LDAP::Connection.new(:host => "fail.SocketError", :port => 636) + connection.socket_class = FakeTCPSocket assert_raise Net::LDAP::Error do - Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + connection.socket end end def test_connection_refused - flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) + connection = Net::LDAP::Connection.new(:host => "fail.Errno::ECONNREFUSED", :port => 636) + connection.socket_class = FakeTCPSocket stderr = capture_stderr do assert_raise Net::LDAP::ConnectionRefusedError do - Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + connection.socket end end assert_equal("Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead.\n", stderr) end def test_raises_unknown_exceptions - error = Class.new(StandardError) - flexmock(TCPSocket).should_receive(:new).and_raise(error) - assert_raise error do - Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + connection = Net::LDAP::Connection.new(:host => "fail.StandardError", :port => 636) + assert_raise Net::LDAP::Error do + connection.socket end end From f6ad189c2e07f55a9c1c17c54c236a98a5727caa Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 10 Nov 2015 17:30:23 -0800 Subject: [PATCH 402/435] use fake for auth adapter test --- test/test_auth_adapter.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_auth_adapter.rb b/test/test_auth_adapter.rb index 7cec57bc..ee7fb4cc 100644 --- a/test/test_auth_adapter.rb +++ b/test/test_auth_adapter.rb @@ -1,9 +1,14 @@ require 'test_helper' class TestAuthAdapter < Test::Unit::TestCase + class FakeSocket + def initialize(*args) + end + end + def test_undefined_auth_adapter - flexmock(TCPSocket).should_receive(:new).ordered.with('ldap.example.com', 379).once.and_return(nil) conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379) + conn.socket_class = FakeSocket assert_raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (foo)" do conn.bind(method: :foo) end From e7cc5ae51ecf21053d21afa1970eced85106233b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 10 Nov 2015 17:30:43 -0800 Subject: [PATCH 403/435] replace ldap tests with fake connection object --- lib/net/ldap.rb | 5 +++++ test/test_ldap.rb | 41 +++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index d952c484..febad64c 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1212,6 +1212,11 @@ def inspect inspected end + # Internal: Set @open_connection for testing + def connection=(connection) + @open_connection = connection + end + private # Yields an open connection if there is one, otherwise establishes a new diff --git a/test/test_ldap.rb b/test/test_ldap.rb index f30416b2..b8c8afdf 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -1,6 +1,28 @@ require 'test_helper' class TestLDAPInstrumentation < Test::Unit::TestCase + # Fake Net::LDAP::Connection for testing + class FakeConnection + # It's difficult to instantiate Net::LDAP::PDU objects. Faking out what we + # need here until that object is brought under test and has it's constructor + # cleaned up. + class Result < Struct.new(:success?, :result_code); end + + def initialize + @bind_success = Result.new(true, Net::LDAP::ResultCodeSuccess) + @search_success = Result.new(true, Net::LDAP::ResultCodeSizeLimitExceeded) + end + + def bind(args = {}) + @bind_success + end + + def search(*args) + yield @search_success if block_given? + @search_success + end + end + def setup @connection = flexmock(:connection, :close => true) flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection) @@ -15,8 +37,9 @@ def setup def test_instrument_bind events = @service.subscribe "bind.net_ldap" - bind_result = flexmock(:bind_result, :success? => true) - flexmock(@connection).should_receive(:bind).with(Hash).and_return(bind_result) + fake_connection = FakeConnection.new + @subject.connection = fake_connection + bind_result = fake_connection.bind assert @subject.bind @@ -28,10 +51,9 @@ def test_instrument_bind def test_instrument_search events = @service.subscribe "search.net_ldap" - flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess)) - flexmock(@connection).should_receive(:search).with(Hash, Proc). - yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). - and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSuccess)) + fake_connection = FakeConnection.new + @subject.connection = fake_connection + entry = fake_connection.search refute_nil @subject.search(:filter => "(uid=user1)") @@ -44,10 +66,9 @@ def test_instrument_search def test_instrument_search_with_size events = @service.subscribe "search.net_ldap" - flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess)) - flexmock(@connection).should_receive(:search).with(Hash, Proc). - yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")). - and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSizeLimitExceeded)) + fake_connection = FakeConnection.new + @subject.connection = fake_connection + entry = fake_connection.search refute_nil @subject.search(:filter => "(uid=user1)", :size => 1) From 7969aa93506f1d477f5dcd6055ec8f85b986fe4b Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 11 Nov 2015 09:12:29 -0800 Subject: [PATCH 404/435] some cleanup --- lib/net/ldap/auth_adapter/gss_spnego.rb | 9 +++++---- lib/net/ldap/error.rb | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index e251f038..b4fec88c 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -29,10 +29,11 @@ def bind(auth) t3_msg.serialize } - Net::LDAP::AuthAdapter::Sasl.new(@connection). - bind(:method => :sasl, :mechanism => "GSS-SPNEGO", - :initial_credential => NTLM::Message::Type1.new.serialize, - :challenge_response => nego) + Net::LDAP::AuthAdapter::Sasl.new(@connection).bind \ + :method => :sasl, + :mechanism => "GSS-SPNEGO", + :initial_credential => NTLM::Message::Type1.new.serialize, + :challenge_response => nego end end end diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index 9f157195..50442d06 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -21,6 +21,7 @@ def message end private + def warn_deprecation_message warn "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead." end From 59378248e900abc9244ceae2becacb9b2f0530fb Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 11 Nov 2015 09:16:00 -0800 Subject: [PATCH 405/435] release 0.12.1 --- History.rdoc | 5 +++++ lib/net/ldap/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index 1e0270a8..dbf7ee63 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,8 @@ +=== Net::LDAP 0.12.1 + +* Whitespace formatting cleanup {#236}[https://github.com/ruby-ldap/ruby-net-ldap/pull/236] +* Set operation result if LDAP server is not accessible {#232}[https://github.com/ruby-ldap/ruby-net-ldap/pull/232] + === Net::LDAP 0.12.0 * DRY up connection handling logic {#224}[https://github.com/ruby-ldap/ruby-net-ldap/pull/224] diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 219b4156..cbe858ab 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.12.0" + VERSION = "0.12.1" end end From 9f29e158d310dc1c9a7084a87b7d57d4aa47683c Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 11 Nov 2015 09:33:07 -0800 Subject: [PATCH 406/435] Release 0.12.1 --- net-ldap.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 97c12906..99e6e72e 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -33,4 +33,5 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.add_development_dependency("rake", "~> 10.0") s.add_development_dependency("rubocop", "~> 0.28.0") s.add_development_dependency("test-unit") + s.add_development_dependency("byebug") end From 11ad9053d7548b1315441d88263c5361e4e8f294 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 25 Nov 2015 18:45:37 +0900 Subject: [PATCH 407/435] Net::LDAP#encryption accepts string --- lib/net/ldap.rb | 6 ++++-- test/test_ldap.rb | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 0ec7fbb7..223f8175 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -589,9 +589,11 @@ def authenticate(username, password) # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } # } def encryption(args) - case args + return if args.nil? + + case method = args.to_sym when :simple_tls, :start_tls - args = { :method => args, :tls_options => {} } + args = { :method => method, :tls_options => {} } end @encryption = args end diff --git a/test/test_ldap.rb b/test/test_ldap.rb index f30416b2..0c241f69 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -64,4 +64,10 @@ def test_obscure_auth @subject.auth "joe_user", password assert_not_include(@subject.inspect, password) end + + def test_encryption + enc = @subject.encryption('start_tls') + + assert_equal enc[:method], :start_tls + end end From 6a2f702504f89854e4442d3b934b6536522462a1 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Wed, 25 Nov 2015 19:00:46 +0900 Subject: [PATCH 408/435] Giving Hash, it is used as encryption options. --- lib/net/ldap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 223f8175..aef8df60 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -590,6 +590,7 @@ def authenticate(username, password) # } def encryption(args) return if args.nil? + return @encryption = args if args.is_a? Hash case method = args.to_sym when :simple_tls, :start_tls From 0062027f234d6d7a52e27b3c77d0eb1a653a48f8 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Tue, 1 Dec 2015 22:46:48 +0900 Subject: [PATCH 409/435] Drop support for ruby 1.9.3 --- .travis.yml | 3 ++- net-ldap.gemspec | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4131d6e4..8ad98d0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: ruby rvm: - - 1.9.3 - 2.0.0 - 2.1 - 2.2 # optional + - 2.3.0-preview1 - ruby-head - jruby-19mode - jruby-head @@ -21,6 +21,7 @@ script: bundle exec rake ci matrix: allow_failures: + - rvm: 2.3.0-preview1 - rvm: ruby-head - rvm: jruby-19mode - rvm: jruby-head diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 99e6e72e..66bd5c8a 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -26,7 +26,7 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] - s.required_ruby_version = ">= 1.9.3" + s.required_ruby_version = ">= 2.0.0" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} s.add_development_dependency("flexmock", "~> 1.3") From 737c484db2d54728740b2f252ad18b3d654b687a Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Thu, 3 Dec 2015 06:14:56 +0900 Subject: [PATCH 410/435] Remove 2.3.0-preview since ruby-head already is included --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ad98d0f..b6dadb8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ rvm: - 2.1 - 2.2 # optional - - 2.3.0-preview1 - ruby-head - jruby-19mode - jruby-head @@ -21,7 +20,6 @@ script: bundle exec rake ci matrix: allow_failures: - - rvm: 2.3.0-preview1 - rvm: ruby-head - rvm: jruby-19mode - rvm: jruby-head From def2c463d4cea77a5e6d40690def1b2a9a8a8f7f Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sun, 13 Dec 2015 22:30:40 +0900 Subject: [PATCH 411/435] Deprecate encrypt method --- lib/net/ldap.rb | 97 +++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index aef8df60..2a7f0106 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -461,11 +461,52 @@ def self.result2string(code) #:nodoc: # call to #search, that value will override any treebase value you give # here. # * :encryption => specifies the encryption to be used in communicating - # with the LDAP server. The value is either a Hash containing additional - # parameters, or the Symbol :simple_tls, which is equivalent to - # specifying the Hash {:method => :simple_tls}. There is a fairly large - # range of potential values that may be given for this parameter. See - # #encryption for details. + # with the LDAP server. The value must be a Hash containing additional + # parameters, which consists of two keys: + # method: - :simple_tls or :start_tls + # options: - Hash of options for that method + # The :simple_tls encryption method encrypts all communications + # with the LDAP server. It completely establishes SSL/TLS encryption with + # the LDAP server before any LDAP-protocol data is exchanged. There is no + # plaintext negotiation and no special encryption-request controls are + # sent to the server. The :simple_tls option is the simplest, easiest + # way to encrypt communications between Net::LDAP and LDAP servers. + # It's intended for cases where you have an implicit level of trust in the + # authenticity of the LDAP server. No validation of the LDAP server's SSL + # certificate is performed. This means that :simple_tls will not produce + # errors if the LDAP server's encryption certificate is not signed by a + # well-known Certification Authority. If you get communications or + # protocol errors when using this option, check with your LDAP server + # administrator. Pay particular attention to the TCP port you are + # connecting to. It's impossible for an LDAP server to support plaintext + # LDAP communications and simple TLS connections on the same port. + # The standard TCP port for unencrypted LDAP connections is 389, but the + # standard port for simple-TLS encrypted connections is 636. Be sure you + # are using the correct port. + # + # The :start_tls like the :simple_tls encryption method also encrypts all + # communcations with the LDAP server. With the exception that it operates + # over the standard TCP port. + # + # In order to verify certificates and enable other TLS options, the + # :tls_options hash can be passed alongside :simple_tls or :start_tls. + # This hash contains any options that can be passed to + # OpenSSL::SSL::SSLContext#set_params(). The most common options passed + # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, + # which contains a path to a Certificate Authority file (PEM-encoded). + # + # Example for a default setup without custom settings: + # { + # :method => :simple_tls, + # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS + # } + # + # Example for specifying a CA-File and only allowing TLSv1.1 connections: + # + # { + # :method => :start_tls, + # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } + # } # * :force_no_page => Set to true to prevent paged results even if your # server says it supports them. This is a fix for MS Active Directory # * :instrumentation_service => An object responsible for instrumenting @@ -482,7 +523,7 @@ def initialize(args = {}) @auth = args[:auth] || DefaultAuth @base = args[:base] || DefaultTreebase @force_no_page = args[:force_no_page] || DefaultForceNoPage - encryption args[:encryption] # may be nil + @encryption = args[:encryption] # may be nil if pr = @auth[:password] and pr.respond_to?(:call) @auth[:password] = pr.call @@ -546,48 +587,8 @@ def authenticate(username, password) # additional capabilities are added, more configuration values will be # added here. # - # The :simple_tls encryption method encrypts all communications - # with the LDAP server. It completely establishes SSL/TLS encryption with - # the LDAP server before any LDAP-protocol data is exchanged. There is no - # plaintext negotiation and no special encryption-request controls are - # sent to the server. The :simple_tls option is the simplest, easiest - # way to encrypt communications between Net::LDAP and LDAP servers. - # It's intended for cases where you have an implicit level of trust in the - # authenticity of the LDAP server. No validation of the LDAP server's SSL - # certificate is performed. This means that :simple_tls will not produce - # errors if the LDAP server's encryption certificate is not signed by a - # well-known Certification Authority. If you get communications or - # protocol errors when using this option, check with your LDAP server - # administrator. Pay particular attention to the TCP port you are - # connecting to. It's impossible for an LDAP server to support plaintext - # LDAP communications and simple TLS connections on the same port. - # The standard TCP port for unencrypted LDAP connections is 389, but the - # standard port for simple-TLS encrypted connections is 636. Be sure you - # are using the correct port. - # - # The :start_tls like the :simple_tls encryption method also encrypts all - # communcations with the LDAP server. With the exception that it operates - # over the standard TCP port. - # - # In order to verify certificates and enable other TLS options, the - # :tls_options hash can be passed alongside :simple_tls or :start_tls. - # This hash contains any options that can be passed to - # OpenSSL::SSL::SSLContext#set_params(). The most common options passed - # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, - # which contains a path to a Certificate Authority file (PEM-encoded). - # - # Example for a default setup without custom settings: - # { - # :method => :simple_tls, - # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS - # } - # - # Example for specifying a CA-File and only allowing TLSv1.1 connections: - # - # { - # :method => :start_tls, - # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } - # } + # This method is deprecated. + # def encryption(args) return if args.nil? return @encryption = args if args.is_a? Hash From 9f9abd35ac8daa3cd4568f98ef20853346f33c34 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Mon, 14 Dec 2015 00:50:46 +0900 Subject: [PATCH 412/435] When calling Net::LDAP#encryption, it shows deprecation warning. --- lib/net/ldap.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 2a7f0106..d76c4767 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -590,6 +590,7 @@ def authenticate(username, password) # This method is deprecated. # def encryption(args) + warn "Deprecation warning: please give :encryption option as a Hash to Net::LDAP.new" return if args.nil? return @encryption = args if args.is_a? Hash From ecce488daed676351b561e39a2dae1147983c939 Mon Sep 17 00:00:00 2001 From: Andi Bachmann Date: Mon, 14 Dec 2015 14:21:20 +0100 Subject: [PATCH 413/435] . adds correct UTF-8 encoding --- lib/net/ber.rb | 38 ++++++++++++++++++++++++++++++++++---- test/ber/test_ber.rb | 10 +++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index b4b9e9da..498b8aaf 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -293,13 +293,43 @@ def to_arr ## # A String object with a BER identifier attached. +# class Net::BER::BerIdentifiedString < String attr_accessor :ber_identifier + + # The binary data provided when parsing the result of the LDAP search + # has the encoding 'ASCII-8BIT' (which is basically 'BINARY', or 'unknown'). + # + # This is the kind of a backtrace showing how the binary `data` comes to + # BerIdentifiedString.new(data): + # + # @conn.read_ber(syntax) + # -> StringIO.new(self).read_ber(syntax), i.e. included from module + # -> Net::BER::BERParser.read_ber(syntax) + # -> (private)Net::BER::BERParser.parse_ber_object(syntax, id, data) + # + # In the `#parse_ber_object` method `data`, according to its OID, is being + # 'casted' to one of the Net::BER:BerIdentifiedXXX classes. + # + # As we are using LDAP v3 we can safely assume that the data is encoded + # in UTF-8 and therefore the only thing to be done when instantiating is to + # switch the encoding from 'ASCII-8BIT' to 'UTF-8'. + # + # Unfortunately, there are some ActiveDirectory specific attributes + # (like `objectguid`) that should remain binary (do they really?). + # Using the `#valid_encoding?` we can trap this cases. Special cases like + # Japanese, Korean, etc. encodings might also profit from this. However + # I have no clue how this encodings function. def initialize args - super begin - args.respond_to?(:encode) ? args.encode('UTF-8') : args - rescue - args + super + # + # Check the encoding of the newly created String and set the encoding + # to 'UTF-8' (NOTE: we do NOT change the bytes, but only set the + # encoding to 'UTF-8'). + current_encoding = encoding + if current_encoding == Encoding::BINARY + force_encoding('UTF-8') + force_encoding(current_encoding) unless valid_encoding? end end end diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 92b3902d..ae17ddd1 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -130,12 +130,20 @@ def test_binary_data def test_ascii_data_in_utf8 data = "some text".force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) + + assert bis.valid_encoding?, "should be a valid encoding" + assert_equal "UTF-8", bis.encoding.name + end + + def test_umlaut_data_in_utf8 + data = "Müller".force_encoding("UTF-8") + bis = Net::BER::BerIdentifiedString.new(data) assert bis.valid_encoding?, "should be a valid encoding" assert_equal "UTF-8", bis.encoding.name end - def test_ut8_data_in_utf8 + def test_utf8_data_in_utf8 data = ["e4b8ad"].pack("H*").force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) From 34ea9538c89759f426f44a978cfcc23e7c7103ac Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Tue, 5 Jan 2016 09:28:40 +0900 Subject: [PATCH 414/435] Update bundler before installing gems with bundler --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index b6dadb8d..fc764963 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,9 @@ rvm: env: - INTEGRATION=openldap +before_install: + - gem update bundler + install: - if [ "$INTEGRATION" = "openldap" ]; then sudo script/install-openldap; fi - bundle install From b05d766c5c2786568717d891ccfad6ccab605355 Mon Sep 17 00:00:00 2001 From: Stefano Tortarolo Date: Thu, 17 Dec 2015 10:46:08 +0000 Subject: [PATCH 415/435] Remove trailing spaces --- lib/net/ber.rb | 14 +++++++------- test/ber/test_ber.rb | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 498b8aaf..c34de6ba 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -293,24 +293,24 @@ def to_arr ## # A String object with a BER identifier attached. -# +# class Net::BER::BerIdentifiedString < String attr_accessor :ber_identifier # The binary data provided when parsing the result of the LDAP search # has the encoding 'ASCII-8BIT' (which is basically 'BINARY', or 'unknown'). - # + # # This is the kind of a backtrace showing how the binary `data` comes to # BerIdentifiedString.new(data): # # @conn.read_ber(syntax) # -> StringIO.new(self).read_ber(syntax), i.e. included from module - # -> Net::BER::BERParser.read_ber(syntax) + # -> Net::BER::BERParser.read_ber(syntax) # -> (private)Net::BER::BERParser.parse_ber_object(syntax, id, data) - # + # # In the `#parse_ber_object` method `data`, according to its OID, is being # 'casted' to one of the Net::BER:BerIdentifiedXXX classes. - # + # # As we are using LDAP v3 we can safely assume that the data is encoded # in UTF-8 and therefore the only thing to be done when instantiating is to # switch the encoding from 'ASCII-8BIT' to 'UTF-8'. @@ -322,9 +322,9 @@ class Net::BER::BerIdentifiedString < String # I have no clue how this encodings function. def initialize args super - # + # # Check the encoding of the newly created String and set the encoding - # to 'UTF-8' (NOTE: we do NOT change the bytes, but only set the + # to 'UTF-8' (NOTE: we do NOT change the bytes, but only set the # encoding to 'UTF-8'). current_encoding = encoding if current_encoding == Encoding::BINARY diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index ae17ddd1..95cfe1ae 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -130,11 +130,11 @@ def test_binary_data def test_ascii_data_in_utf8 data = "some text".force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) - + assert bis.valid_encoding?, "should be a valid encoding" assert_equal "UTF-8", bis.encoding.name end - + def test_umlaut_data_in_utf8 data = "Müller".force_encoding("UTF-8") bis = Net::BER::BerIdentifiedString.new(data) From f6611e26273fa9df44e4ac1ae63e006f08c23e1d Mon Sep 17 00:00:00 2001 From: Stefano Tortarolo Date: Thu, 17 Dec 2015 10:47:44 +0000 Subject: [PATCH 416/435] Use Socket.tcp instead of TCPSocket.new to provide socket timeouts This patch prevents LDAP connections to hang up for an eccessive amount of time and instead returns earlier in case of failures (e.g., packets dropped). A new option is now exposed through Net::LDAP: - connect_timeout: sets a timeout for socket#connect (defaults to 1s) It also provides an integration test to validate the new behaviour (#244) --- lib/net/ldap.rb | 24 ++++++++++++++------- lib/net/ldap/connection.rb | 9 +++++++- script/install-openldap | 3 +++ test/integration/test_bind.rb | 8 +++++++ test/test_auth_adapter.rb | 3 ++- test/test_ldap_connection.rb | 39 +++++++++++++++++++++-------------- 6 files changed, 62 insertions(+), 24 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index d76c4767..27fd56a7 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -79,6 +79,14 @@ class LDAP # # p ldap.get_operation_result # +# === Setting connect timeout +# +# By default, Net::LDAP uses TCP sockets with a connection timeout of 5 seconds. +# +# This value can be tweaked passing the :connect_timeout parameter. +# i.e. +# ldap = Net::LDAP.new ..., +# :connect_timeout => 3 # # == A Brief Introduction to LDAP # @@ -487,22 +495,22 @@ def self.result2string(code) #:nodoc: # The :start_tls like the :simple_tls encryption method also encrypts all # communcations with the LDAP server. With the exception that it operates # over the standard TCP port. - # + # # In order to verify certificates and enable other TLS options, the # :tls_options hash can be passed alongside :simple_tls or :start_tls. # This hash contains any options that can be passed to # OpenSSL::SSL::SSLContext#set_params(). The most common options passed # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, # which contains a path to a Certificate Authority file (PEM-encoded). - # + # # Example for a default setup without custom settings: # { # :method => :simple_tls, # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS # } - # + # # Example for specifying a CA-File and only allowing TLSv1.1 connections: - # + # # { # :method => :start_tls, # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } @@ -524,6 +532,7 @@ def initialize(args = {}) @base = args[:base] || DefaultTreebase @force_no_page = args[:force_no_page] || DefaultForceNoPage @encryption = args[:encryption] # may be nil + @connect_timeout = args[:connect_timeout] if pr = @auth[:password] and pr.respond_to?(:call) @auth[:password] = pr.call @@ -587,7 +596,7 @@ def authenticate(username, password) # additional capabilities are added, more configuration values will be # added here. # - # This method is deprecated. + # This method is deprecated. # def encryption(args) warn "Deprecation warning: please give :encryption option as a Hash to Net::LDAP.new" @@ -1247,8 +1256,9 @@ def new_connection :port => @port, :hosts => @hosts, :encryption => @encryption, - :instrumentation_service => @instrumentation_service - rescue Errno::ECONNREFUSED, Net::LDAP::ConnectionRefusedError => e + :instrumentation_service => @instrumentation_service, + :connect_timeout => @connect_timeout + rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, Net::LDAP::ConnectionRefusedError => e @result = { :resultCode => 52, :errorMessage => ResultStrings[ResultCodeUnavailable] diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 71ff7b43..e23972c4 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -3,6 +3,9 @@ class Net::LDAP::Connection #:nodoc: include Net::LDAP::Instrumentation + # Seconds before failing for socket connect timeout + DefaultConnectTimeout = 5 + LdapVersion = 3 MaxSaslChallenges = 10 @@ -31,10 +34,14 @@ def open_connection(server) hosts = server[:hosts] encryption = server[:encryption] + socket_opts = { + connect_timeout: server[:connect_timeout] || DefaultConnectTimeout + } + errors = [] hosts.each do |host, port| begin - prepare_socket(server.merge(socket: TCPSocket.new(host, port))) + prepare_socket(server.merge(socket: Socket.tcp(host, port, socket_opts))) return rescue Net::LDAP::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e diff --git a/script/install-openldap b/script/install-openldap index b9efac98..efb0cbaa 100755 --- a/script/install-openldap +++ b/script/install-openldap @@ -109,4 +109,7 @@ chgrp ssl-cert /etc/ssl/private/ldap01_slapd_key.pem chmod g+r /etc/ssl/private/ldap01_slapd_key.pem chmod o-r /etc/ssl/private/ldap01_slapd_key.pem +# Drop packets on a secondary port used to specific timeout tests +iptables -A OUTPUT -p tcp -j DROP --dport 8389 + service slapd restart diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index bea6b034..b7fa35bc 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -5,6 +5,14 @@ def test_bind_success assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect end + def test_bind_timeout + @ldap.port = 8389 + error = assert_raise Net::LDAP::Error do + @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1") + end + assert_equal('Connection timed out - user specified timeout', error.message) + end + def test_bind_anonymous_fail refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect diff --git a/test/test_auth_adapter.rb b/test/test_auth_adapter.rb index 7cec57bc..badde0fb 100644 --- a/test/test_auth_adapter.rb +++ b/test/test_auth_adapter.rb @@ -2,7 +2,8 @@ class TestAuthAdapter < Test::Unit::TestCase def test_undefined_auth_adapter - flexmock(TCPSocket).should_receive(:new).ordered.with('ldap.example.com', 379).once.and_return(nil) + flexmock(Socket).should_receive(:tcp).ordered.with('ldap.example.com', 379, { connect_timeout: 5 }).once.and_return(nil) + conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379) assert_raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (foo)" do conn.bind(method: :foo) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index b4c77615..727b82a4 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -15,8 +15,8 @@ def test_list_of_hosts_with_first_host_successful ['test2.mocked.com', 636], ['test3.mocked.com', 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_return(nil) - flexmock(TCPSocket).should_receive(:new).ordered.never + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[0], { connect_timeout: 5 }).once.and_return(nil) + flexmock(Socket).should_receive(:tcp).ordered.never Net::LDAP::Connection.new(:hosts => hosts) end @@ -26,9 +26,9 @@ def test_list_of_hosts_with_first_host_failure ['test2.mocked.com', 636], ['test3.mocked.com', 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_return(nil) - flexmock(TCPSocket).should_receive(:new).ordered.never + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[0], { connect_timeout: 5 }).once.and_raise(SocketError) + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[1], { connect_timeout: 5 }).once.and_return(nil) + flexmock(Socket).should_receive(:tcp).ordered.never Net::LDAP::Connection.new(:hosts => hosts) end @@ -38,17 +38,17 @@ def test_list_of_hosts_with_all_hosts_failure ['test2.mocked.com', 636], ['test3.mocked.com', 636], ] - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[0]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[1]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.with(*hosts[2]).once.and_raise(SocketError) - flexmock(TCPSocket).should_receive(:new).ordered.never + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[0], { connect_timeout: 5 }).once.and_raise(SocketError) + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[1], { connect_timeout: 5 }).once.and_raise(SocketError) + flexmock(Socket).should_receive(:tcp).ordered.with(*hosts[2], { connect_timeout: 5 }).once.and_raise(SocketError) + flexmock(Socket).should_receive(:tcp).ordered.never assert_raise Net::LDAP::ConnectionError do Net::LDAP::Connection.new(:hosts => hosts) end end def test_result_for_connection_failed_is_set - flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) + flexmock(Socket).should_receive(:tcp).and_raise(Errno::ECONNREFUSED) ldap_client = Net::LDAP.new(host: '127.0.0.1', port: 12345) @@ -67,14 +67,14 @@ def test_unresponsive_host end def test_blocked_port - flexmock(TCPSocket).should_receive(:new).and_raise(SocketError) + flexmock(Socket).should_receive(:tcp).and_raise(SocketError) assert_raise Net::LDAP::Error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end end def test_connection_refused - flexmock(TCPSocket).should_receive(:new).and_raise(Errno::ECONNREFUSED) + flexmock(Socket).should_receive(:tcp).and_raise(Errno::ECONNREFUSED) stderr = capture_stderr do assert_raise Net::LDAP::ConnectionRefusedError do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) @@ -83,9 +83,18 @@ def test_connection_refused assert_equal("Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead.\n", stderr) end + def test_connection_timedout + flexmock(Socket).should_receive(:tcp).and_raise(Errno::ETIMEDOUT) + stderr = capture_stderr do + assert_raise Net::LDAP::Error do + Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) + end + end + end + def test_raises_unknown_exceptions error = Class.new(StandardError) - flexmock(TCPSocket).should_receive(:new).and_raise(error) + flexmock(Socket).should_receive(:tcp).and_raise(error) assert_raise error do Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end @@ -328,7 +337,7 @@ class TestLDAPConnectionErrors < Test::Unit::TestCase def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) - flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + flexmock(Socket).should_receive(:tcp).and_return(@tcp_socket) @connection = Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636) end @@ -357,7 +366,7 @@ class TestLDAPConnectionInstrumentation < Test::Unit::TestCase def setup @tcp_socket = flexmock(:connection) @tcp_socket.should_receive(:write) - flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket) + flexmock(Socket).should_receive(:tcp).and_return(@tcp_socket) @service = MockInstrumentationService.new @connection = Net::LDAP::Connection.new \ From e63134e3142a7e9e515c3b8e1695dbb43c56bccb Mon Sep 17 00:00:00 2001 From: Rufus Post Date: Mon, 15 Dec 2014 17:26:12 +1100 Subject: [PATCH 417/435] Support for rfc3062 Password Modify, closes #163 This implements the password modify extended request http://tools.ietf.org/html/rfc3062 --- Contributors.rdoc | 1 + lib/net/ber.rb | 1 + lib/net/ldap.rb | 53 +++++++++++++++- lib/net/ldap/connection.rb | 45 +++++++++++++ lib/net/ldap/pdu.rb | 26 +++++++- test/fixtures/openldap/slapd.conf.ldif | 2 +- test/integration/test_password_modify.rb | 80 ++++++++++++++++++++++++ 7 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 test/integration/test_password_modify.rb diff --git a/Contributors.rdoc b/Contributors.rdoc index e40b20db..137394f8 100644 --- a/Contributors.rdoc +++ b/Contributors.rdoc @@ -22,3 +22,4 @@ Contributions since: * David J. Lee (DavidJLee) * Cody Cutrer (ccutrer) * WoodsBagotAndreMarquesLee +* Rufus Post (mynameisrufus) diff --git a/lib/net/ber.rb b/lib/net/ber.rb index c34de6ba..3bc7a2ba 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -106,6 +106,7 @@ module Net # :nodoc: # CHARACTER STRINGC29: 61 (0x3d, 0b00111101) # BMPStringP30: 30 (0x1e, 0b00011110) # BMPStringC30: 62 (0x3e, 0b00111110) + # ExtendedResponseC107: 139 (0x8b, 0b010001011) # module BER VERSION = Net::LDAP::VERSION diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 27fd56a7..455bbd6e 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -323,7 +323,14 @@ class Net::LDAP :constructed => constructed, } + universal = { + constructed: { + 107 => :array #ExtendedResponse (PasswdModifyResponseValue) + } + } + AsnSyntax = Net::BER.compile_syntax(:application => application, + :universal => universal, :context_specific => context_specific) DefaultHost = "127.0.0.1" @@ -332,7 +339,8 @@ class Net::LDAP DefaultTreebase = "dc=com" DefaultForceNoPage = false - StartTlsOid = "1.3.6.1.4.1.1466.20037" + StartTlsOid = '1.3.6.1.4.1.1466.20037' + PasswdModifyOid = '1.3.6.1.4.1.4203.1.11.1' # https://tools.ietf.org/html/rfc4511#section-4.1.9 # https://tools.ietf.org/html/rfc4511#appendix-A @@ -651,8 +659,11 @@ def self.open(args) #++ def get_operation_result result = @result - result = result.result if result.is_a?(Net::LDAP::PDU) os = OpenStruct.new + if result.is_a?(Net::LDAP::PDU) + os.extended_response = result.extended_response + result = result.result + end if result.is_a?(Hash) # We might get a hash of LDAP response codes instead of a simple # numeric code. @@ -1041,6 +1052,44 @@ def modify(args) end end + # Password Modify + # + # Change existing password: + # + # dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' + # auth = { + # method: :simple, + # username: dn, + # password: 'passworD1' + # } + # ldap.password_modify(dn: dn, + # auth: auth, + # old_password: 'passworD1', + # new_password: 'passworD2') + # + # Or get the LDAP server to generate a password for you: + # + # dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' + # auth = { + # method: :simple, + # username: dn, + # password: 'passworD1' + # } + # ldap.password_modify(dn: dn, + # auth: auth, + # old_password: 'passworD1') + # + # ldap.get_operation_result.extended_response[0][0] #=> 'VtcgGf/G' + # + def password_modify(args) + instrument "modify_password.net_ldap", args do |payload| + @result = use_connection(args) do |conn| + conn.password_modify(args) + end + @result.success? + end + end + # Add a value to an attribute. Takes the full DN of the entry to modify, # the name (Symbol or String) of the attribute, and the value (String or # Array). If the attribute does not exist (and there are no schema diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e23972c4..67757323 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -539,6 +539,51 @@ def modify(args) pdu end + ## + # Password Modify + # + # http://tools.ietf.org/html/rfc3062 + # + # passwdModifyOID OBJECT IDENTIFIER ::= 1.3.6.1.4.1.4203.1.11.1 + # + # PasswdModifyRequestValue ::= SEQUENCE { + # userIdentity [0] OCTET STRING OPTIONAL + # oldPasswd [1] OCTET STRING OPTIONAL + # newPasswd [2] OCTET STRING OPTIONAL } + # + # PasswdModifyResponseValue ::= SEQUENCE { + # genPasswd [0] OCTET STRING OPTIONAL } + # + # Encoded request: + # + # 00\x02\x01\x02w+\x80\x171.3.6.1.4.1.4203.1.11.1\x81\x100\x0E\x81\x05old\x82\x05new + # + def password_modify(args) + dn = args[:dn] + raise ArgumentError, 'DN is required' if !dn || dn.empty? + + ext_seq = [Net::LDAP::PasswdModifyOid.to_ber_contextspecific(0)] + + unless args[:old_password].nil? + pwd_seq = [args[:old_password].to_ber(0x81)] + pwd_seq << args[:new_password].to_ber(0x82) unless args[:new_password].nil? + ext_seq << pwd_seq.to_ber_sequence.to_ber(0x81) + end + + request = ext_seq.to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + + message_id = next_msgid + + write(request, nil, message_id) + pdu = queued_read(message_id) + + if !pdu || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse + raise Net::LDAP::ResponseMissingError, "response missing or invalid" + end + + pdu + end + #-- # TODO: need to support a time limit, in case the server fails to respond. # Unlike other operation-methods in this class, we return a result hash diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index f749f669..5527c1df 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -74,6 +74,7 @@ class Error < RuntimeError; end attr_reader :search_referrals attr_reader :search_parameters attr_reader :bind_parameters + attr_reader :extended_response ## # Returns RFC-2251 Controls if any. @@ -120,7 +121,7 @@ def initialize(ber_object) when UnbindRequest parse_unbind_request(ber_object[1]) when ExtendedResponse - parse_ldap_result(ber_object[1]) + parse_extended_response(ber_object[1]) else raise LdapPduError.new("unknown pdu-type: #{@app_tag}") end @@ -180,6 +181,29 @@ def parse_ldap_result(sequence) end private :parse_ldap_result + ## + # Parse an extended response + # + # http://www.ietf.org/rfc/rfc2251.txt + # + # Each Extended operation consists of an Extended request and an + # Extended response. + # + # ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + # requestName [0] LDAPOID, + # requestValue [1] OCTET STRING OPTIONAL } + + def parse_extended_response(sequence) + sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length." + @ldap_result = { + :resultCode => sequence[0], + :matchedDN => sequence[1], + :errorMessage => sequence[2] + } + @extended_response = sequence[3] + end + private :parse_extended_response + ## # A Bind Response may have an additional field, ID [7], serverSaslCreds, # per RFC 2251 pgh 4.2.3. diff --git a/test/fixtures/openldap/slapd.conf.ldif b/test/fixtures/openldap/slapd.conf.ldif index 6ba5cf77..77a6af09 100644 --- a/test/fixtures/openldap/slapd.conf.ldif +++ b/test/fixtures/openldap/slapd.conf.ldif @@ -3,7 +3,7 @@ objectClass: olcGlobal cn: config olcPidFile: /var/run/slapd/slapd.pid olcArgsFile: /var/run/slapd/slapd.args -olcLogLevel: none +olcLogLevel: -1 olcToolThreads: 1 dn: olcDatabase={-1}frontend,cn=config diff --git a/test/integration/test_password_modify.rb b/test/integration/test_password_modify.rb new file mode 100644 index 00000000..12583363 --- /dev/null +++ b/test/integration/test_password_modify.rb @@ -0,0 +1,80 @@ +require_relative '../test_helper' + +class TestPasswordModifyIntegration < LDAPIntegrationTestCase + def setup + super + @ldap.authenticate 'cn=admin,dc=rubyldap,dc=com', 'passworD1' + + @dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' + + attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: 'modify-password-user1', + cn: 'modify-password-user1', + sn: 'modify-password-user1', + mail: 'modify-password-user1@rubyldap.com', + userPassword: 'passworD1' + } + unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect + end + assert @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + + @auth = { + method: :simple, + username: @dn, + password: 'passworD1' + } + end + + def test_password_modify + assert @ldap.password_modify(dn: @dn, + auth: @auth, + old_password: 'passworD1', + new_password: 'passworD2') + + assert @ldap.get_operation_result.extended_response.nil?, + 'Should not have generated a new password' + + refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), + 'Old password should no longer be valid' + + assert @ldap.bind(username: @dn, password: 'passworD2', method: :simple), + 'New password should be valid' + end + + def test_password_modify_generate + assert @ldap.password_modify(dn: @dn, + auth: @auth, + old_password: 'passworD1') + + generated_password = @ldap.get_operation_result.extended_response[0][0] + + assert generated_password, 'Should have generated a password' + + refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), + 'Old password should no longer be valid' + + assert @ldap.bind(username: @dn, password: generated_password, method: :simple), + 'New password should be valid' + end + + def test_password_modify_generate_no_old_password + assert @ldap.password_modify(dn: @dn, + auth: @auth) + + generated_password = @ldap.get_operation_result.extended_response[0][0] + + assert generated_password, 'Should have generated a password' + + refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), + 'Old password should no longer be valid' + + assert @ldap.bind(username: @dn, password: generated_password, method: :simple), + 'New password should be valid' + end + + def teardown + @ldap.delete dn: @dn + end +end From aa0638cdb2fc3907db706464911d0a96a0c9340f Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 6 Jan 2016 15:14:06 -0800 Subject: [PATCH 418/435] release 0.13.0 --- History.rdoc | 10 ++++++++++ lib/net/ldap/version.rb | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index dbf7ee63..f6dbbc61 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,13 @@ +=== Net::LDAP 0.13.0 + +* Set a connect_timeout for the creation of a socket {#243}[https://github.com/ruby-ldap/ruby-net-ldap/pull/243] +* Update bundler before installing gems with bundler {#245}[https://github.com/ruby-ldap/ruby-net-ldap/pull/245] +* Net::LDAP#encryption accepts string {#239}[https://github.com/ruby-ldap/ruby-net-ldap/pull/239] +* Adds correct UTF-8 encoding to Net::BER::BerIdentifiedString {#242}[https://github.com/ruby-ldap/ruby-net-ldap/pull/242] +* Remove 2.3.0-preview since ruby-head already is included {#241}[https://github.com/ruby-ldap/ruby-net-ldap/pull/241] +* Drop support for ruby 1.9.3 {#240}[https://github.com/ruby-ldap/ruby-net-ldap/pull/240] +* Fixed capitalization of StartTLSError {#234}[https://github.com/ruby-ldap/ruby-net-ldap/pull/234] + === Net::LDAP 0.12.1 * Whitespace formatting cleanup {#236}[https://github.com/ruby-ldap/ruby-net-ldap/pull/236] diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index cbe858ab..259355b2 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.12.1" + VERSION = "0.13.0" end end From 67d8311aed6de49f4f2007e67b5e01ac7787c88e Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 7 Jan 2016 10:04:35 -0800 Subject: [PATCH 419/435] Release 0.13.0 From 1aab8c9a86d88c378bbc203449341d61d6e7c2f7 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 10:32:14 -0800 Subject: [PATCH 420/435] set socket_class in initialize --- lib/net/ldap/connection.rb | 26 +++++++++++++------------- test/test_auth_adapter.rb | 3 +-- test/test_ldap_connection.rb | 24 +++++++++--------------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e9a79414..39cfd970 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -21,19 +21,10 @@ def initialize(server = {}) @server = server @instrumentation_service = server[:instrumentation_service] - yield self if block_given? - end + # Allows tests to parameterize what socket class to use + @socket_class = server.fetch(:socket_class, DefaultSocket) - # Allows tests to parameterize what socket class to use - def socket_class - @socket_class || DefaultSocket - end - - # Wrap around Socket.tcp to normalize with other Socket initializers - class DefaultSocket - def self.new(host, port, socket_opts = {}) - Socket.tcp(host, port, socket_opts) - end + yield self if block_given? end def socket_class=(socket_class) @@ -59,7 +50,7 @@ def open_connection(server) errors = [] hosts.each do |host, port| begin - prepare_socket(server.merge(socket: socket_class.new(host, port, socket_opts))) + prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts))) return rescue Net::LDAP::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e @@ -690,4 +681,13 @@ def socket @conn end + + private + + # Wrap around Socket.tcp to normalize with other Socket initializers + class DefaultSocket + def self.new(host, port, socket_opts = {}) + Socket.tcp(host, port, socket_opts) + end + end end # class Connection diff --git a/test/test_auth_adapter.rb b/test/test_auth_adapter.rb index ee7fb4cc..9e4c6002 100644 --- a/test/test_auth_adapter.rb +++ b/test/test_auth_adapter.rb @@ -7,8 +7,7 @@ def initialize(*args) end def test_undefined_auth_adapter - conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379) - conn.socket_class = FakeSocket + conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379, :socket_class => FakeSocket) assert_raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (foo)" do conn.bind(method: :foo) end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 12ca3d71..51e30c3f 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -29,8 +29,7 @@ def test_list_of_hosts_with_first_host_successful ["fail.SocketError", 636], ] - connection = Net::LDAP::Connection.new(:hosts => hosts) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:hosts => hosts, :socket_class => FakeTCPSocket) connection.socket end @@ -41,8 +40,7 @@ def test_list_of_hosts_with_first_host_failure ["fail.SocketError", 636], ] - connection = Net::LDAP::Connection.new(:hosts => hosts) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:hosts => hosts, :socket_class => FakeTCPSocket) connection.socket end @@ -53,8 +51,7 @@ def test_list_of_hosts_with_all_hosts_failure ["fail.SocketError", 636], ] - connection = Net::LDAP::Connection.new(:hosts => hosts) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:hosts => hosts, :socket_class => FakeTCPSocket) assert_raise Net::LDAP::ConnectionError do connection.socket end @@ -75,24 +72,21 @@ def test_result_for_connection_failed_is_set end def test_unresponsive_host - connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636, :socket_class => FakeTCPSocket) assert_raise Net::LDAP::Error do connection.socket end end def test_blocked_port - connection = Net::LDAP::Connection.new(:host => "fail.SocketError", :port => 636) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:host => "fail.SocketError", :port => 636, :socket_class => FakeTCPSocket) assert_raise Net::LDAP::Error do connection.socket end end def test_connection_refused - connection = Net::LDAP::Connection.new(:host => "fail.Errno::ECONNREFUSED", :port => 636) - connection.socket_class = FakeTCPSocket + connection = Net::LDAP::Connection.new(:host => "fail.Errno::ECONNREFUSED", :port => 636, :socket_class => FakeTCPSocket) stderr = capture_stderr do assert_raise Net::LDAP::ConnectionRefusedError do connection.socket @@ -102,7 +96,7 @@ def test_connection_refused end def test_connection_timeout - connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636) + connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636, :socket_class => FakeTCPSocket) stderr = capture_stderr do assert_raise Net::LDAP::Error do connection.socket @@ -111,8 +105,8 @@ def test_connection_timeout end def test_raises_unknown_exceptions - connection = Net::LDAP::Connection.new(:host => "fail.StandardError", :port => 636) - assert_raise Net::LDAP::Error do + connection = Net::LDAP::Connection.new(:host => "fail.StandardError", :port => 636, :socket_class => FakeTCPSocket) + assert_raise StandardError do connection.socket end end From 0dec1d971701db1e5e65f59ce9c8bec1b5f6f3e2 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:41:25 -0800 Subject: [PATCH 421/435] fix multiline blocks --- lib/net/ldap.rb | 8 ++++---- lib/net/ldap/auth_adapter/gss_spnego.rb | 2 -- lib/net/ldap/auth_adapter/sasl.rb | 4 ++-- lib/net/ldap/connection.rb | 8 ++++---- lib/net/ldap/entry.rb | 4 ++-- lib/net/ldap/filter.rb | 4 ++-- lib/net/snmp.rb | 12 ++++++------ test/test_filter.rb | 4 ++-- test/test_snmp.rb | 8 ++++---- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 455bbd6e..6dbda5a3 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -775,10 +775,10 @@ def search(args = {}) instrument "search.net_ldap", args do |payload| @result = use_connection(args) do |conn| - conn.search(args) { |entry| + conn.search(args) do |entry| result_set << entry if result_set yield entry if block_given? - } + end end if return_result_set @@ -917,7 +917,7 @@ def bind(auth = @auth) # end def bind_as(args = {}) result = false - open { |me| + open do |me| rs = search args if rs and rs.first and dn = rs.first.dn password = args[:password] @@ -925,7 +925,7 @@ def bind_as(args = {}) result = rs if bind(:method => :simple, :username => dn, :password => password) end - } + end result end diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index b4fec88c..fffdc04f 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -22,12 +22,10 @@ def bind(auth) user, psw = [auth[:username] || auth[:dn], auth[:password]] raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) - nego = proc { |challenge| t2_msg = NTLM::Message.parse(challenge) t3_msg = t2_msg.response({ :user => user, :password => psw }, { :ntlmv2 => true }) t3_msg.serialize - } Net::LDAP::AuthAdapter::Sasl.new(@connection).bind \ :method => :sasl, diff --git a/lib/net/ldap/auth_adapter/sasl.rb b/lib/net/ldap/auth_adapter/sasl.rb index fa7315b5..ebbe4e63 100644 --- a/lib/net/ldap/auth_adapter/sasl.rb +++ b/lib/net/ldap/auth_adapter/sasl.rb @@ -33,7 +33,7 @@ def bind(auth) message_id = @connection.next_msgid n = 0 - loop { + loop do sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) request = [ Net::LDAP::Connection::LdapVersion.to_ber, "".to_ber, sasl @@ -50,7 +50,7 @@ def bind(auth) raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) cred = chall.call(pdu.result_server_sasl_creds) - } + end raise Net::LDAP::SASLChallengeOverflowError, "why are we here?" end diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 67757323..0064cbda 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -500,14 +500,14 @@ def search(args = nil) def self.modify_ops(operations) ops = [] if operations - operations.each { |op, attrib, values| + operations.each do |op, attrib, values| # TODO, fix the following line, which gives a bogus error if the # opcode is invalid. op_ber = MODIFY_OPERATIONS[op.to_sym].to_ber_enumerated values = [ values ].flatten.map { |v| v.to_ber if v }.to_ber_set values = [ attrib.to_s.to_ber, values ].to_ber_sequence ops << [ op_ber, values ].to_ber - } + end end ops end @@ -594,9 +594,9 @@ def password_modify(args) def add(args) add_dn = args[:dn] or raise Net::LDAP::EmptyDNError, "Unable to add empty DN" add_attrs = [] - a = args[:attributes] and a.each { |k, v| + a = args[:attributes] and a.each do |k, v| add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence - } + end message_id = next_msgid request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(Net::LDAP::PDU::AddRequest) diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index c2615268..f46912ba 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -141,10 +141,10 @@ def attribute_names # (possibly empty) \Array of data values. def each # :yields: attribute-name, data-values-array if block_given? - attribute_names.each {|a| + attribute_names.each do|a| attr_name,values = a,self[a] yield attr_name, values - } + end end end alias_method :each_attribute, :each diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index aad84f83..d4542e3d 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -287,7 +287,7 @@ def parse_ber(ber) when 0xa4 # context-specific constructed 4, "substring" str = "" final = false - ber.last.each { |b| + ber.last.each do |b| case b.ber_identifier when 0x80 # context-specific primitive 0, SubstringFilter "initial" raise Net::LDAP::SubstringFilterError, "Unrecognized substring filter; bad initial value." if str.length > 0 @@ -298,7 +298,7 @@ def parse_ber(ber) str += "*#{escape(b)}" final = true end - } + end str += "*" unless final eq(ber.first.to_s, str) when 0xa5 # context-specific constructed 5, "greaterOrEqual" diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 501df851..fe7a2899 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -227,9 +227,9 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map {|n,v| + @variables.map do|n,v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } + end ].to_ber_sequence ].to_ber_contextspecific(0) when :get_next_request @@ -238,9 +238,9 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map {|n,v| + @variables.map do|n,v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } + end ].to_ber_sequence ].to_ber_contextspecific(1) when :get_response @@ -249,9 +249,9 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map {|n,v| + @variables.map do|n,v| [n.to_ber_oid, v.to_ber].to_ber_sequence - } + end ].to_ber_sequence ].to_ber_contextspecific(2) else diff --git a/test/test_filter.rb b/test/test_filter.rb index 2bcccd92..dd4577eb 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -13,11 +13,11 @@ def test_invalid_filter_string end def test_invalid_filter - assert_raises(Net::LDAP::OperatorError) { + assert_raises(Net::LDAP::OperatorError) do # This test exists to prove that our constructor blocks unknown filter # types. All filters must be constructed using helpers. Filter.__send__(:new, :xx, nil, nil) - } + end end def test_to_s diff --git a/test/test_snmp.rb b/test/test_snmp.rb index fe1ee168..6a809a80 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -16,9 +16,9 @@ def self.raw_string(s) def test_invalid_packet data = "xxxx" - assert_raise(Net::BER::BerError) { + assert_raise(Net::BER::BerError) do ary = data.read_ber(Net::SNMP::AsnSyntax) - } + end end # The method String#read_ber! added by Net::BER consumes a well-formed BER @@ -40,9 +40,9 @@ def _test_consume_string end def test_weird_packet - assert_raise(Net::SnmpPdu::Error) { + assert_raise(Net::SnmpPdu::Error) do Net::SnmpPdu.parse("aaaaaaaaaaaaaa") - } + end end def test_get_request From 63d7bbb3198445bf3509aebc7e7841661a5b2a7a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:41:35 -0800 Subject: [PATCH 422/435] fix trailing underscore --- test/integration/test_search.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index b56052ce..96f9ff42 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -57,7 +57,7 @@ def test_search_timeout entries << entry end - payload, _ = events.pop + payload, = events.pop assert_equal 5, payload[:time] assert_equal entries, result end From 17e2fe6ed983f1ccd12b32d33022868dd5b11893 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:41:48 -0800 Subject: [PATCH 423/435] fix multiline block --- lib/net/ldap/auth_adapter/gss_spnego.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index fffdc04f..9f773454 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -22,10 +22,12 @@ def bind(auth) user, psw = [auth[:username] || auth[:dn], auth[:password]] raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) + nego = proc do |challenge| t2_msg = NTLM::Message.parse(challenge) t3_msg = t2_msg.response({ :user => user, :password => psw }, { :ntlmv2 => true }) t3_msg.serialize + end Net::LDAP::AuthAdapter::Sasl.new(@connection).bind \ :method => :sasl, From 2702b89bac61d26440a17794297c873acd9044fd Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:46:41 -0800 Subject: [PATCH 424/435] fix multiline blocks --- test/test_ldif.rb | 8 ++++---- testserver/ldapserver.rb | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 988c3155..8181671c 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -68,10 +68,10 @@ def test_ldif_with_base64_dn_and_continuation_lines # TODO, INADEQUATE. We need some more tests # to verify the content. def test_ldif - File.open(TestLdifFilename, "r") {|f| + File.open(TestLdifFilename, "r") do |f| ds = Net::LDAP::Dataset::read_ldif(f) assert_equal(13, ds.length) - } + end end # Must test folded lines and base64-encoded lines as well as normal ones. @@ -84,13 +84,13 @@ def test_to_ldif entries = data.lines.grep(/^dn:\s*/) { $'.chomp } dn_entries = entries.dup - ds = Net::LDAP::Dataset::read_ldif(io) { |type, value| + ds = Net::LDAP::Dataset::read_ldif(io) do |type, value| case type when :dn assert_equal(dn_entries.first, value) dn_entries.shift end - } + end assert_equal(entries.size, ds.size) assert_equal(entries.sort, ds.to_ldif.grep(/^dn:\s*/) { $'.chomp }) end diff --git a/testserver/ldapserver.rb b/testserver/ldapserver.rb index eba130ce..24578ffb 100644 --- a/testserver/ldapserver.rb +++ b/testserver/ldapserver.rb @@ -133,21 +133,21 @@ def handle_search_request pdu # TODO, what if this returns nil? filter = Net::LDAP::Filter.parse_ldap_filter( filters ) - $ldif.each {|dn, entry| + $ldif.each do |dn, entry| if filter.match( entry ) attrs = [] - entry.each {|k, v| + entry.each do |k, v| if requested_attrs == :all or requested_attrs.include?(k.downcase) attrvals = v.map {|v1| v1.to_ber}.to_ber_set attrs << [k.to_ber, attrvals].to_ber_sequence end - } + end appseq = [dn.to_ber, attrs.to_ber_sequence].to_ber_appsequence(4) pkt = [msgid.to_ber, appseq].to_ber_sequence send_data pkt end - } + end send_ldap_response 5, pdu[0].to_i, 0, "", "Was that what you wanted?" @@ -201,10 +201,9 @@ def load_test_data require 'net/ldap' - EventMachine.run { + EventMachine.run do $logger.info "starting LDAP server on 127.0.0.1 port 3890" EventMachine.start_server "127.0.0.1", 3890, LdapServer EventMachine.add_periodic_timer 60, proc {$logger.info "heartbeat"} - } + end end - From defcc866c40a0439f498cd3bfdb965870e19d7c2 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:53:54 -0800 Subject: [PATCH 425/435] add explicit exceptions for this project --- .rubocop.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index 85ffa202..084ca199 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,3 +3,12 @@ inherit_from: .rubocop_todo.yml AllCops: Exclude: - 'pkg/**/*' + +Style/ExtraSpacing: + Enabled: false + +Lint/AssignmentInCondition: + Enabled: false + +Style/ParallelAssignment: + Enabled: false From 5a06857f8adfff1d63477a455b765389264a0f1a Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Fri, 8 Jan 2016 11:54:06 -0800 Subject: [PATCH 426/435] regenerate rubocop_todo --- .rubocop_todo.yml | 448 +++++++++++++++++++++++++++++++++------------- 1 file changed, 323 insertions(+), 125 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5a5dcbc7..4c6c68d2 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,43 +1,61 @@ -# This configuration was generated by `rubocop --auto-gen-config` -# on 2014-12-19 15:32:44 +1100 using RuboCop version 0.28.0. +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2016-01-08 11:47:42 -0800 using RuboCop version 0.35.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 12 -# Configuration parameters: AllowSafeAssignment. -Lint/AssignmentInCondition: - Enabled: false - # Offense count: 1 -# Configuration parameters: AlignWith, SupportedStyles. +# Cop supports --auto-correct. +# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect. Lint/EndAlignment: Enabled: false +# Offense count: 1 +Lint/NonLocalExitFromIterator: + Exclude: + - 'lib/net/ldap/connection.rb' + # Offense count: 1 Lint/RescueException: - Enabled: false + Exclude: + - 'lib/net/ldap/pdu.rb' # Offense count: 1 Lint/ShadowingOuterLocalVariable: - Enabled: false + Exclude: + - 'lib/net/ldap/instrumentation.rb' -# Offense count: 9 +# Offense count: 10 # Cop supports --auto-correct. +# Configuration parameters: IgnoreEmptyBlocks. Lint/UnusedBlockArgument: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/snmp.rb' + - 'test/support/vm/openldap/Vagrantfile' # Offense count: 3 # Cop supports --auto-correct. +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. Lint/UnusedMethodArgument: - Enabled: false + Exclude: + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/pdu.rb' + - 'test/test_search.rb' -# Offense count: 7 +# Offense count: 9 Lint/UselessAssignment: - Enabled: false - -# Offense count: 47 + Exclude: + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/password.rb' + - 'test/integration/test_add.rb' + - 'test/test_ldap_connection.rb' + - 'test/test_search.rb' + - 'test/test_snmp.rb' + +# Offense count: 48 Metrics/AbcSize: Max: 114 @@ -45,16 +63,16 @@ Metrics/AbcSize: Metrics/BlockNesting: Max: 4 -# Offense count: 9 +# Offense count: 10 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 470 + Max: 423 -# Offense count: 20 +# Offense count: 21 Metrics/CyclomaticComplexity: Max: 41 -# Offense count: 193 +# Offense count: 229 # Configuration parameters: AllowURI, URISchemes. Metrics/LineLength: Max: 360 @@ -64,54 +82,76 @@ Metrics/LineLength: Metrics/MethodLength: Max: 130 +# Offense count: 1 +# Configuration parameters: CountComments. +Metrics/ModuleLength: + Max: 104 + # Offense count: 13 Metrics/PerceivedComplexity: - Max: 36 + Max: 37 # Offense count: 1 Style/AccessorMethodName: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' # Offense count: 4 # Cop supports --auto-correct. Style/AlignArray: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter/sasl.rb' + - 'lib/net/ldap/connection.rb' -# Offense count: 3 +# Offense count: 10 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/AlignParameters: - Enabled: false + Exclude: + - 'test/ber/test_ber.rb' + - 'test/integration/test_ber.rb' + - 'test/integration/test_bind.rb' + - 'test/integration/test_password_modify.rb' -# Offense count: 36 +# Offense count: 37 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/AndOr: - Enabled: false + Exclude: + - 'lib/net/ber/ber_parser.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/pdu.rb' + - 'testserver/ldapserver.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/BarePercentLiterals: - Enabled: false + Exclude: + - 'test/test_entry.rb' # Offense count: 1 # Cop supports --auto-correct. Style/BlockComments: - Enabled: false + Exclude: + - 'test/test_rename.rb' -# Offense count: 20 -# Cop supports --auto-correct. -Style/Blocks: - Enabled: false - -# Offense count: 2 +# Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/BracesAroundHashParameters: - Enabled: false + Exclude: + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' + - 'lib/net/snmp.rb' + - 'test/test_auth_adapter.rb' + - 'test/test_ldap_connection.rb' # Offense count: 4 +# Cop supports --auto-correct. # Configuration parameters: IndentWhenRelativeTo, SupportedStyles, IndentOneStep. Style/CaseIndentation: Enabled: false @@ -119,41 +159,82 @@ Style/CaseIndentation: # Offense count: 4 # Cop supports --auto-correct. Style/CharacterLiteral: - Enabled: false + Exclude: + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/entry.rb' + +# Offense count: 1 +Style/ClassAndModuleCamelCase: + Exclude: + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' -# Offense count: 22 +# Offense count: 23 # Configuration parameters: EnforcedStyle, SupportedStyles. Style/ClassAndModuleChildren: Enabled: false -# Offense count: 1 +# Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/ClassCheck: - Enabled: false + Exclude: + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap/error.rb' # Offense count: 13 # Cop supports --auto-correct. Style/ColonMethodCall: - Enabled: false + Exclude: + - 'test/test_ldif.rb' + - 'test/test_ssl_ber.rb' -# Offense count: 2 +# Offense count: 1 +# Cop supports --auto-correct. # Configuration parameters: Keywords. Style/CommentAnnotation: - Enabled: false + Exclude: + - 'lib/net/ber.rb' -# Offense count: 86 +# Offense count: 88 Style/ConstantName: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/pdu.rb' + - 'lib/net/snmp.rb' + - 'test/test_ldif.rb' + - 'testserver/ldapserver.rb' # Offense count: 18 # Cop supports --auto-correct. Style/DeprecatedHashMethods: - Enabled: false + Exclude: + - 'lib/net/snmp.rb' + - 'test/test_ldap_connection.rb' + - 'test/test_ldif.rb' + - 'test/test_search.rb' -# Offense count: 46 +# Offense count: 21 +# Configuration parameters: Exclude. Style/Documentation: - Enabled: false + Exclude: + - 'spec/**/*' + - 'test/**/*' + - 'lib/net/ber.rb' + - 'lib/net/ber/core_ext.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter.rb' + - 'lib/net/ldap/auth_adapter/sasl.rb' + - 'lib/net/ldap/auth_adapter/simple.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/error.rb' + - 'lib/net/ldap/instrumentation.rb' + - 'lib/net/ldap/password.rb' + - 'lib/net/ldap/pdu.rb' + - 'lib/net/ldap/version.rb' + - 'lib/net/snmp.rb' + - 'testserver/ldapserver.rb' # Offense count: 23 # Cop supports --auto-correct. @@ -164,77 +245,106 @@ Style/DotPosition: # Offense count: 1 # Cop supports --auto-correct. Style/ElseAlignment: - Enabled: false + Exclude: + - 'testserver/ldapserver.rb' -# Offense count: 4 +# Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: AllowAdjacentOneLineDefs. Style/EmptyLineBetweenDefs: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/snmp.rb' -# Offense count: 9 +# Offense count: 8 # Cop supports --auto-correct. Style/EmptyLines: - Enabled: false + Exclude: + - 'lib/net/snmp.rb' + - 'testserver/ldapserver.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/EmptyLinesAroundClassBody: - Enabled: false + Exclude: + - 'test/test_snmp.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/EmptyLinesAroundModuleBody: - Enabled: false + Exclude: + - 'testserver/ldapserver.rb' # Offense count: 3 +# Cop supports --auto-correct. Style/EvenOdd: - Enabled: false + Exclude: + - 'lib/net/ldap/dn.rb' # Offense count: 1 # Configuration parameters: Exclude. Style/FileName: - Enabled: false + Exclude: + - 'lib/net-ldap.rb' # Offense count: 9 # Configuration parameters: AllowedVariables. Style/GlobalVars: - Enabled: false + Exclude: + - 'testserver/ldapserver.rb' -# Offense count: 3 +# Offense count: 4 # Configuration parameters: MinBodyLength. Style/GuardClause: - Enabled: false + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' -# Offense count: 150 +# Offense count: 149 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues. Style/HashSyntax: Enabled: false -# Offense count: 8 +# Offense count: 7 +# Cop supports --auto-correct. # Configuration parameters: MaxLineLength. Style/IfUnlessModifier: - Enabled: false + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ber/core_ext/integer.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/snmp.rb' # Offense count: 2 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: SupportedStyles. Style/IndentHash: - Enabled: false + EnforcedStyle: consistent -# Offense count: 6 +# Offense count: 10 # Cop supports --auto-correct. # Configuration parameters: Width. Style/IndentationWidth: - Enabled: false + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ldap/password.rb' + - 'lib/net/snmp.rb' + - 'test/test_snmp.rb' + - 'testserver/ldapserver.rb' -# Offense count: 2 +# Offense count: 3 # Cop supports --auto-correct. Style/LeadingCommentSpace: - Enabled: false + Exclude: + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' # Offense count: 21 # Cop supports --auto-correct. @@ -255,66 +365,85 @@ Style/MultilineOperationIndentation: # Offense count: 1 Style/MultilineTernaryOperator: - Enabled: false + Exclude: + - 'lib/net/ldap/connection.rb' # Offense count: 1 # Cop supports --auto-correct. Style/NegatedIf: - Enabled: false + Exclude: + - 'test/test_helper.rb' # Offense count: 1 # Cop supports --auto-correct. Style/NegatedWhile: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' # Offense count: 3 +# Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. Style/Next: - Enabled: false + Exclude: + - 'lib/net/ldap/connection.rb' + - 'testserver/ldapserver.rb' # Offense count: 1 # Cop supports --auto-correct. Style/NilComparison: - Enabled: false + Exclude: + - 'lib/net/ldap/connection.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: IncludeSemanticChanges. Style/NonNilCheck: - Enabled: false + Exclude: + - 'lib/net/ber/ber_parser.rb' # Offense count: 1 # Cop supports --auto-correct. Style/Not: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' -# Offense count: 10 +# Offense count: 11 # Cop supports --auto-correct. Style/NumericLiterals: MinDigits: 8 # Offense count: 3 Style/OpMethod: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: AllowSafeAssignment. Style/ParenthesesAroundCondition: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' + - 'lib/net/ldap/auth_adapter/sasl.rb' + - 'lib/net/ldap/auth_adapter/simple.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: - Enabled: false + Exclude: + - 'net-ldap.gemspec' + - 'test/test_entry.rb' # Offense count: 11 # Cop supports --auto-correct. Style/PerlBackrefs: - Enabled: false + Exclude: + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/filter.rb' + - 'testserver/ldapserver.rb' -# Offense count: 9 +# Offense count: 10 # Configuration parameters: EnforcedStyle, SupportedStyles. Style/RaiseArgs: Enabled: false @@ -322,54 +451,96 @@ Style/RaiseArgs: # Offense count: 1 # Cop supports --auto-correct. Style/RedundantBegin: - Enabled: false + Exclude: + - 'lib/net/snmp.rb' -# Offense count: 3 +# Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: - Enabled: false + Exclude: + - 'lib/net/ber/core_ext/string.rb' + - 'lib/net/ldap/auth_adapter.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/password.rb' -# Offense count: 7 +# Offense count: 6 # Cop supports --auto-correct. Style/RedundantSelf: - Enabled: false + Exclude: + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ber/core_ext/string.rb' + - 'lib/net/ldap/dn.rb' + - 'lib/net/ldap/filter.rb' -# Offense count: 1 -# Configuration parameters: MaxSlashes. +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. Style/RegexpLiteral: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' + - 'net-ldap.gemspec' -# Offense count: 2 +# Offense count: 1 +# Cop supports --auto-correct. Style/RescueModifier: - Enabled: false + Exclude: + - 'test/ber/core_ext/test_string.rb' -# Offense count: 7 +# Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: - Enabled: false + Exclude: + - 'lib/net/ldap/dn.rb' + - 'lib/net/ldap/error.rb' + - 'testserver/ldapserver.rb' -# Offense count: 61 +# Offense count: 66 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/SignalException: - Enabled: false + Exclude: + - 'lib/net/ber/ber_parser.rb' + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter.rb' + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' + - 'lib/net/ldap/auth_adapter/sasl.rb' + - 'lib/net/ldap/auth_adapter/simple.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/dn.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/password.rb' + - 'lib/net/ldap/pdu.rb' + - 'lib/net/snmp.rb' # Offense count: 2 # Configuration parameters: Methods. Style/SingleLineBlockParams: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' # Offense count: 2 # Cop supports --auto-correct. Style/SingleSpaceBeforeFirstArg: - Enabled: false + Exclude: + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/instrumentation.rb' # Offense count: 24 # Cop supports --auto-correct. Style/SpaceAfterComma: - Enabled: false + Exclude: + - 'lib/net/ber/core_ext/integer.rb' + - 'lib/net/ber/core_ext/string.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/snmp.rb' + - 'test/ber/core_ext/test_array.rb' + - 'test/ber/test_ber.rb' + - 'test/test_dn.rb' # Offense count: 2 # Cop supports --auto-correct. @@ -377,10 +548,16 @@ Style/SpaceAfterComma: Style/SpaceAroundEqualsInParameterDefault: Enabled: false -# Offense count: 8 +# Offense count: 9 # Cop supports --auto-correct. +# Configuration parameters: MultiSpaceAllowedForOperators. Style/SpaceAroundOperators: - Enabled: false + Exclude: + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + - 'test/test_entry.rb' + - 'test/test_ldap_connection.rb' # Offense count: 2 # Cop supports --auto-correct. @@ -397,7 +574,13 @@ Style/SpaceInsideBlockBraces: # Offense count: 37 # Cop supports --auto-correct. Style/SpaceInsideBrackets: - Enabled: false + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/filter.rb' + - 'test/test_ldap_connection.rb' + - 'testserver/ldapserver.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -408,52 +591,67 @@ Style/SpaceInsideHashLiteralBraces: # Offense count: 20 # Cop supports --auto-correct. Style/SpaceInsideParens: - Enabled: false + Exclude: + - 'lib/net/ldap/entry.rb' + - 'lib/net/snmp.rb' + - 'test/test_password.rb' + - 'testserver/ldapserver.rb' # Offense count: 5 # Cop supports --auto-correct. Style/SpecialGlobalVars: - Enabled: false + Exclude: + - 'lib/net/snmp.rb' + - 'net-ldap.gemspec' + - 'testserver/ldapserver.rb' -# Offense count: 645 +# Offense count: 663 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. Style/StringLiterals: Enabled: false -# Offense count: 10 +# Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. Style/SymbolProc: - Enabled: false + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/filter.rb' + - 'test/ber/test_ber.rb' + - 'test/test_ldif.rb' + - 'testserver/ldapserver.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/TrailingBlankLines: - Enabled: false - -# Offense count: 9 +# Offense count: 12 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. Style/TrailingComma: - Enabled: false - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, Whitelist. -Style/TrivialAccessors: - Enabled: false + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/dn.rb' + - 'lib/net/snmp.rb' + - 'test/ber/test_ber.rb' + - 'test/test_dn.rb' + - 'test/test_filter.rb' + - 'test/test_ldap_connection.rb' + - 'testserver/ldapserver.rb' # Offense count: 5 # Cop supports --auto-correct. Style/UnneededPercentQ: - Enabled: false + Exclude: + - 'net-ldap.gemspec' + - 'test/test_entry.rb' # Offense count: 1 +# Cop supports --auto-correct. # Configuration parameters: MaxLineLength. Style/WhileUntilModifier: - Enabled: false + Exclude: + - 'lib/net/ldap/filter.rb' # Offense count: 1 # Cop supports --auto-correct. From 64d9f28820c90f1fb2b01f6d0da84d4c8f4c88a8 Mon Sep 17 00:00:00 2001 From: Rufus Post Date: Mon, 11 Jan 2016 14:24:48 +1100 Subject: [PATCH 427/435] fix deprecated hash methods --- .rubocop_todo.yml | 9 --------- lib/net/snmp.rb | 2 +- test/test_ldap_connection.rb | 18 +++++++++--------- test/test_ldif.rb | 12 ++++++------ test/test_search.rb | 4 ++-- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4c6c68d2..3007d218 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -206,15 +206,6 @@ Style/ConstantName: - 'test/test_ldif.rb' - 'testserver/ldapserver.rb' -# Offense count: 18 -# Cop supports --auto-correct. -Style/DeprecatedHashMethods: - Exclude: - - 'lib/net/snmp.rb' - - 'test/test_ldap_connection.rb' - - 'test/test_ldif.rb' - - 'test/test_search.rb' - # Offense count: 21 # Configuration parameters: Exclude. Style/Documentation: diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index fe7a2899..8767e399 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -191,7 +191,7 @@ def pdu_type= t end def error_status= es - unless ErrorStatusCodes.has_key?(es) + unless ErrorStatusCodes.key?(es) raise Error.new("unknown error-status: #{es}") end @error_status = es diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 51e30c3f..d6f75906 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -399,8 +399,8 @@ def test_write_net_ldap_connection_event # a write event payload, result = events.pop - assert payload.has_key?(:result) - assert payload.has_key?(:content_length) + assert payload.key?(:result) + assert payload.key?(:content_length) end def test_read_net_ldap_connection_event @@ -416,7 +416,7 @@ def test_read_net_ldap_connection_event # a read event payload, result = events.pop - assert payload.has_key?(:result) + assert payload.key?(:result) assert_equal read_result, result end @@ -433,9 +433,9 @@ def test_parse_pdu_net_ldap_connection_event # a parse_pdu event payload, result = events.pop - assert payload.has_key?(:pdu) - assert payload.has_key?(:app_tag) - assert payload.has_key?(:message_id) + assert payload.key?(:pdu) + assert payload.key?(:app_tag) + assert payload.key?(:message_id) assert_equal Net::LDAP::PDU::BindResult, payload[:app_tag] assert_equal 1, payload[:message_id] pdu = payload[:pdu] @@ -455,7 +455,7 @@ def test_bind_net_ldap_connection_event # a read event payload, result = events.pop - assert payload.has_key?(:result) + assert payload.key?(:result) assert result.success?, "should be success" end @@ -482,8 +482,8 @@ def test_search_net_ldap_connection_event # a search event payload, result = events.pop - assert payload.has_key?(:result) - assert payload.has_key?(:filter) + assert payload.key?(:result) + assert payload.key?(:filter) assert_equal "(uid=user1)", payload[:filter].to_s assert result diff --git a/test/test_ldif.rb b/test/test_ldif.rb index 8181671c..b86eb2fb 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -38,31 +38,31 @@ def test_ldif_with_password def test_ldif_with_continuation_lines ds = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) - assert_equal(true, ds.has_key?("abcdefghijklmn")) + assert_equal(true, ds.key?("abcdefghijklmn")) end def test_ldif_with_continuation_lines_and_extra_whitespace ds1 = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) - assert_equal(true, ds1.has_key?("abcdefg hijklmn")) + assert_equal(true, ds1.key?("abcdefg hijklmn")) ds2 = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hij klmn\r\n\r\n")) - assert_equal(true, ds2.has_key?("abcdefghij klmn")) + assert_equal(true, ds2.key?("abcdefghij klmn")) end def test_ldif_tab_is_not_continuation ds = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: key\r\n\tnotcontinued\r\n\r\n")) - assert_equal(true, ds.has_key?("key")) + assert_equal(true, ds.key?("key")) end def test_ldif_with_base64_dn str = "dn:: Q049QmFzZTY0IGRuIHRlc3QsT1U9VGVzdCxPVT1Vbml0cyxEQz1leGFtcGxlLERDPWNvbQ==\r\n\r\n" ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) - assert_equal(true, ds.has_key?("CN=Base64 dn test,OU=Test,OU=Units,DC=example,DC=com")) + assert_equal(true, ds.key?("CN=Base64 dn test,OU=Test,OU=Units,DC=example,DC=com")) end def test_ldif_with_base64_dn_and_continuation_lines str = "dn:: Q049QmFzZTY0IGRuIHRlc3Qgd2l0aCBjb250aW51YXRpb24gbGluZSxPVT1UZXN0LE9VPVVua\r\n XRzLERDPWV4YW1wbGUsREM9Y29t\r\n\r\n" ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) - assert_equal(true, ds.has_key?("CN=Base64 dn test with continuation line,OU=Test,OU=Units,DC=example,DC=com")) + assert_equal(true, ds.key?("CN=Base64 dn test with continuation line,OU=Test,OU=Units,DC=example,DC=com")) end # TODO, INADEQUATE. We need some more tests diff --git a/test/test_search.rb b/test/test_search.rb index e349d0b8..c577a6a2 100644 --- a/test/test_search.rb +++ b/test/test_search.rb @@ -32,8 +32,8 @@ def test_instrumentation_publishes_event @connection.search(:filter => "test") payload, result = events.pop - assert payload.has_key?(:result) - assert payload.has_key?(:filter) + assert payload.key?(:result) + assert payload.key?(:filter) assert_equal "test", payload[:filter] end end From 8572cacddae0520a47def01a9fc74818630eb85c Mon Sep 17 00:00:00 2001 From: Rufus Post Date: Mon, 11 Jan 2016 14:18:40 +1100 Subject: [PATCH 428/435] fix space after comma --- .rubocop_todo.yml | 13 ------------- lib/net/ber/core_ext/integer.rb | 2 +- lib/net/ber/core_ext/string.rb | 2 +- lib/net/ldap/dataset.rb | 2 +- lib/net/ldap/entry.rb | 2 +- lib/net/snmp.rb | 12 ++++++------ test/ber/core_ext/test_array.rb | 2 +- test/ber/test_ber.rb | 2 +- test/test_dn.rb | 6 +++--- 9 files changed, 15 insertions(+), 28 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4c6c68d2..747cb8ca 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -529,19 +529,6 @@ Style/SingleSpaceBeforeFirstArg: - 'lib/net/ldap/dataset.rb' - 'lib/net/ldap/instrumentation.rb' -# Offense count: 24 -# Cop supports --auto-correct. -Style/SpaceAfterComma: - Exclude: - - 'lib/net/ber/core_ext/integer.rb' - - 'lib/net/ber/core_ext/string.rb' - - 'lib/net/ldap/dataset.rb' - - 'lib/net/ldap/entry.rb' - - 'lib/net/snmp.rb' - - 'test/ber/core_ext/test_array.rb' - - 'test/ber/test_ber.rb' - - 'test/test_dn.rb' - # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. diff --git a/lib/net/ber/core_ext/integer.rb b/lib/net/ber/core_ext/integer.rb index b2149f9b..78313045 100644 --- a/lib/net/ber/core_ext/integer.rb +++ b/lib/net/ber/core_ext/integer.rb @@ -20,7 +20,7 @@ def to_ber_length_encoding if self <= 127 [self].pack('C') else - i = [self].pack('N').sub(/^[\0]+/,"") + i = [self].pack('N').sub(/^[\0]+/, "") [0x80 + i.length].pack('C') + i end end diff --git a/lib/net/ber/core_ext/string.rb b/lib/net/ber/core_ext/string.rb index e8a43e2c..995d26d4 100644 --- a/lib/net/ber/core_ext/string.rb +++ b/lib/net/ber/core_ext/string.rb @@ -75,6 +75,6 @@ def read_ber!(syntax = nil) end def reject_empty_ber_arrays - self.gsub(/0\000/n,'') + self.gsub(/0\000/n, '') end end diff --git a/lib/net/ldap/dataset.rb b/lib/net/ldap/dataset.rb index 54fc1a07..47810ce7 100644 --- a/lib/net/ldap/dataset.rb +++ b/lib/net/ldap/dataset.rb @@ -141,7 +141,7 @@ def read_ldif(io) # $' is the dn-value # Avoid the Base64 class because not all Ruby versions have it. dn = ($1 == ":") ? $'.unpack('m').shift : $' - ds[dn] = Hash.new { |k,v| k[v] = [] } + ds[dn] = Hash.new { |k, v| k[v] = [] } yield :dn, dn if block_given? elsif line.empty? dn = nil diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index f46912ba..d5068dde 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -142,7 +142,7 @@ def attribute_names def each # :yields: attribute-name, data-values-array if block_given? attribute_names.each do|a| - attr_name,values = a,self[a] + attr_name, values = a, self[a] yield attr_name, values end end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index fe7a2899..2ff49aac 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -148,7 +148,7 @@ def parse_get_request data # data[2] is error_index, always zero. send :error_status=, 0 send :error_index=, 0 - data[3].each do |n,v| + data[3].each do |n, v| # A variable-binding, of which there may be several, # consists of an OID and a BER null. # We're ignoring the null, we might want to verify it instead. @@ -166,7 +166,7 @@ def parse_get_response data send :request_id=, data[0].to_i send :error_status=, data[1].to_i send :error_index=, data[2].to_i - data[3].each do |n,v| + data[3].each do |n, v| # A variable-binding, of which there may be several, # consists of an OID and a BER null. # We're ignoring the null, we might want to verify it instead. @@ -177,7 +177,7 @@ def parse_get_response data def version= ver - unless [0,2].include?(ver) + unless [0, 2].include?(ver) raise Error.new("unknown snmp-version: #{ver}") end @version = ver @@ -227,7 +227,7 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map do|n,v| + @variables.map do|n, v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence end ].to_ber_sequence @@ -238,7 +238,7 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map do|n,v| + @variables.map do|n, v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence end ].to_ber_sequence @@ -249,7 +249,7 @@ def pdu_to_ber_string error_status.to_ber, error_index.to_ber, [ - @variables.map do|n,v| + @variables.map do|n, v| [n.to_ber_oid, v.to_ber].to_ber_sequence end ].to_ber_sequence diff --git a/test/ber/core_ext/test_array.rb b/test/ber/core_ext/test_array.rb index 308fffc5..2d1e957a 100644 --- a/test/ber/core_ext/test_array.rb +++ b/test/ber/core_ext/test_array.rb @@ -6,7 +6,7 @@ def test_control_code_array control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence control_codes << ['1.7.9'.to_ber, false.to_ber].to_ber_sequence control_codes = control_codes.to_ber_sequence - res = [['1.2.3', true],['1.7.9',false]].to_ber_control + res = [['1.2.3', true], ['1.7.9', false]].to_ber_control assert_equal control_codes, res end diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 95cfe1ae..c2f5a568 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -6,7 +6,7 @@ def test_empty_array end def test_array - ary = [1,2,3] + ary = [1, 2, 3] encoded_ary = ary.map { |el| el.to_ber }.to_ber assert_equal ary, encoded_ary.read_ber diff --git a/test/test_dn.rb b/test/test_dn.rb index 0cb2ec5a..5fff6ae8 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -13,17 +13,17 @@ def test_escape_on_initialize def test_to_a dn = Net::LDAP::DN.new('cn=James, ou=Company\\,\\20LLC') - assert_equal ['cn','James','ou','Company, LLC'], dn.to_a + assert_equal ['cn', 'James', 'ou', 'Company, LLC'], dn.to_a end def test_to_a_parenthesis dn = Net::LDAP::DN.new('cn = \ James , ou = "Comp\28ny" ') - assert_equal ['cn',' James','ou','Comp(ny'], dn.to_a + assert_equal ['cn', ' James', 'ou', 'Comp(ny'], dn.to_a end def test_to_a_hash_symbol dn = Net::LDAP::DN.new('1.23.4= #A3B4D5 ,ou=Company') - assert_equal ['1.23.4','#A3B4D5','ou','Company'], dn.to_a + assert_equal ['1.23.4', '#A3B4D5', 'ou', 'Company'], dn.to_a end # TODO: raise a more specific exception than RuntimeError From 0e6808448e5463111372fa01c8b7a490cf6e8b30 Mon Sep 17 00:00:00 2001 From: Rufus Post Date: Mon, 11 Jan 2016 14:15:57 +1100 Subject: [PATCH 429/435] fix space inside brackets --- .rubocop_todo.yml | 11 ----------- lib/net/ber.rb | 2 +- lib/net/ldap.rb | 6 +++--- lib/net/ldap/connection.rb | 8 ++++---- lib/net/ldap/filter.rb | 2 +- test/test_ldap_connection.rb | 14 +++++++------- testserver/ldapserver.rb | 2 +- 7 files changed, 17 insertions(+), 28 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4c6c68d2..469260d5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -571,17 +571,6 @@ Style/SpaceBeforeBlockBraces: Style/SpaceInsideBlockBraces: Enabled: false -# Offense count: 37 -# Cop supports --auto-correct. -Style/SpaceInsideBrackets: - Exclude: - - 'lib/net/ber.rb' - - 'lib/net/ldap.rb' - - 'lib/net/ldap/connection.rb' - - 'lib/net/ldap/filter.rb' - - 'test/test_ldap_connection.rb' - - 'testserver/ldapserver.rb' - # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles. diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 3bc7a2ba..baf08e14 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -235,7 +235,7 @@ def self.compile_syntax(syntax) # TODO 20100327 AZ: Should we be allocating an array of 256 values # that will either be +nil+ or an object type symbol, or should we # allocate an empty Hash since unknown values return +nil+ anyway? - out = [ nil ] * 256 + out = [nil] * 256 syntax.each do |tag_class_id, encodings| tag_class = TAG_CLASS[tag_class_id] encodings.each do |encoding_id, classes| diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 32414250..5f328a24 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -264,14 +264,14 @@ class Net::LDAP SearchScope_BaseObject = 0 SearchScope_SingleLevel = 1 SearchScope_WholeSubtree = 2 - SearchScopes = [ SearchScope_BaseObject, SearchScope_SingleLevel, - SearchScope_WholeSubtree ] + SearchScopes = [SearchScope_BaseObject, SearchScope_SingleLevel, + SearchScope_WholeSubtree] DerefAliases_Never = 0 DerefAliases_Search = 1 DerefAliases_Find = 2 DerefAliases_Always = 3 - DerefAliasesArray = [ DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always ] + DerefAliasesArray = [DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always] primitive = { 2 => :null } # UnbindRequest body constructed = { diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index e16f4096..1ac9dfd7 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -513,9 +513,9 @@ def self.modify_ops(operations) # TODO, fix the following line, which gives a bogus error if the # opcode is invalid. op_ber = MODIFY_OPERATIONS[op.to_sym].to_ber_enumerated - values = [ values ].flatten.map { |v| v.to_ber if v }.to_ber_set - values = [ attrib.to_s.to_ber, values ].to_ber_sequence - ops << [ op_ber, values ].to_ber + values = [values].flatten.map { |v| v.to_ber if v }.to_ber_set + values = [attrib.to_s.to_ber, values].to_ber_sequence + ops << [op_ber, values].to_ber end end ops @@ -604,7 +604,7 @@ def add(args) add_dn = args[:dn] or raise Net::LDAP::EmptyDNError, "Unable to add empty DN" add_attrs = [] a = args[:attributes] and a.each do |k, v| - add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence + add_attrs << [k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set].to_ber_sequence end message_id = next_msgid diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index d4542e3d..084b997d 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -23,7 +23,7 @@ class Net::LDAP::Filter ## # Known filter types. - FilterTypes = [ :ne, :eq, :ge, :le, :and, :or, :not, :ex, :bineq ] + FilterTypes = [:ne, :eq, :ge, :le, :and, :or, :not, :ex, :bineq] def initialize(op, left, right) #:nodoc: unless FilterTypes.include?(op) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 51e30c3f..6b34ab5e 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -112,23 +112,23 @@ def test_raises_unknown_exceptions end def test_modify_ops_delete - args = { :operations => [ [ :delete, "mail" ] ] } + args = { :operations => [[:delete, "mail"]] } result = Net::LDAP::Connection.modify_ops(args[:operations]) - expected = [ "0\r\n\x01\x010\b\x04\x04mail1\x00" ] + expected = ["0\r\n\x01\x010\b\x04\x04mail1\x00"] assert_equal(expected, result) end def test_modify_ops_add - args = { :operations => [ [ :add, "mail", "testuser@example.com" ] ] } + args = { :operations => [[:add, "mail", "testuser@example.com"]] } result = Net::LDAP::Connection.modify_ops(args[:operations]) - expected = [ "0#\n\x01\x000\x1E\x04\x04mail1\x16\x04\x14testuser@example.com" ] + expected = ["0#\n\x01\x000\x1E\x04\x04mail1\x16\x04\x14testuser@example.com"] assert_equal(expected, result) end def test_modify_ops_replace - args = { :operations =>[ [ :replace, "mail", "testuser@example.com" ] ] } + args = { :operations =>[[:replace, "mail", "testuser@example.com"]] } result = Net::LDAP::Connection.modify_ops(args[:operations]) - expected = [ "0#\n\x01\x020\x1E\x04\x04mail1\x16\x04\x14testuser@example.com" ] + expected = ["0#\n\x01\x020\x1E\x04\x04mail1\x16\x04\x14testuser@example.com"] assert_equal(expected, result) end @@ -463,7 +463,7 @@ def test_search_net_ldap_connection_event # search data search_data_ber = Net::BER::BerIdentifiedArray.new([1, [ "uid=user1,ou=People,dc=rubyldap,dc=com", - [ ["uid", ["user1"]] ] + [["uid", ["user1"]]] ]]) search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData search_data = [1, search_data_ber] diff --git a/testserver/ldapserver.rb b/testserver/ldapserver.rb index 24578ffb..25e38799 100644 --- a/testserver/ldapserver.rb +++ b/testserver/ldapserver.rb @@ -156,7 +156,7 @@ def handle_search_request pdu def send_ldap_response pkt_tag, msgid, code, dn, text - send_data( [msgid.to_ber, [code.to_ber, dn.to_ber, text.to_ber].to_ber_appsequence(pkt_tag) ].to_ber ) + send_data( [msgid.to_ber, [code.to_ber, dn.to_ber, text.to_ber].to_ber_appsequence(pkt_tag)].to_ber ) end end From 9d6240317e06d728db123cbbcdb0dacce9638934 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Tue, 12 Jan 2016 10:16:09 -0800 Subject: [PATCH 430/435] fix trailing comma Default is to require a trailing comma. --- .rubocop.yml | 3 +++ .rubocop_todo.yml | 14 -------------- lib/net/ber/ber_parser.rb | 2 +- lib/net/ldap.rb | 16 ++++++++-------- lib/net/ldap/connection.rb | 14 +++++++------- lib/net/ldap/pdu.rb | 4 ++-- lib/net/snmp.rb | 22 +++++++++++----------- test/integration/test_add.rb | 2 +- test/integration/test_ber.rb | 2 +- test/integration/test_delete.rb | 2 +- test/integration/test_open.rb | 2 +- test/integration/test_password_modify.rb | 4 ++-- test/test_filter.rb | 4 ++-- test/test_ldap_connection.rb | 6 +++--- testserver/ldapserver.rb | 4 ++-- 15 files changed, 45 insertions(+), 56 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 084ca199..9870d13e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,3 +12,6 @@ Lint/AssignmentInCondition: Style/ParallelAssignment: Enabled: false + +Style/TrailingComma: + EnforcedStyleForMultiline: comma diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 892dfacf..13e5ac59 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -592,20 +592,6 @@ Style/SymbolProc: - 'test/test_ldif.rb' - 'testserver/ldapserver.rb' -# Offense count: 12 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. -Style/TrailingComma: - Exclude: - - 'lib/net/ldap.rb' - - 'lib/net/ldap/dn.rb' - - 'lib/net/snmp.rb' - - 'test/ber/test_ber.rb' - - 'test/test_dn.rb' - - 'test/test_filter.rb' - - 'test/test_ldap_connection.rb' - - 'testserver/ldapserver.rb' - # Offense count: 5 # Cop supports --auto-correct. Style/UnneededPercentQ: diff --git a/lib/net/ber/ber_parser.rb b/lib/net/ber/ber_parser.rb index 09de8c82..ee69eed8 100644 --- a/lib/net/ber/ber_parser.rb +++ b/lib/net/ber/ber_parser.rb @@ -14,7 +14,7 @@ module Net::BER::BERParser } constructed = { 16 => :array, - 17 => :array + 17 => :array, } universal = { :primitive => primitive, :constructed => constructed } diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 5f328a24..a9c843e7 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -325,8 +325,8 @@ class Net::LDAP universal = { constructed: { - 107 => :array #ExtendedResponse (PasswdModifyResponseValue) - } + 107 => :array, #ExtendedResponse (PasswdModifyResponseValue) + }, } AsnSyntax = Net::BER.compile_syntax(:application => application, @@ -389,14 +389,14 @@ class Net::LDAP ResultCodeCompareFalse, ResultCodeCompareTrue, ResultCodeReferral, - ResultCodeSaslBindInProgress + ResultCodeSaslBindInProgress, ] # nonstandard list of "successful" result codes for searches ResultCodesSearchSuccess = [ ResultCodeSuccess, ResultCodeTimeLimitExceeded, - ResultCodeSizeLimitExceeded + ResultCodeSizeLimitExceeded, ] # map of result code to human message @@ -438,7 +438,7 @@ class Net::LDAP ResultCodeEntryAlreadyExists => "Entry Already Exists", ResultCodeObjectClassModsProhibited => "ObjectClass Modifications Prohibited", ResultCodeAffectsMultipleDSAs => "Affects Multiple DSAs", - ResultCodeOther => "Other" + ResultCodeOther => "Other", } module LDAPControls @@ -591,7 +591,7 @@ def authenticate(username, password) @auth = { :method => :simple, :username => username, - :password => password + :password => password, } end alias_method :auth, :authenticate @@ -1208,7 +1208,7 @@ def search_root_dse :supportedExtension, :supportedFeatures, :supportedLdapVersion, - :supportedSASLMechanisms + :supportedSASLMechanisms, ]) (rs and rs.first) or Net::LDAP::Entry.new end @@ -1319,7 +1319,7 @@ def new_connection rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, Net::LDAP::ConnectionRefusedError => e @result = { :resultCode => 52, - :errorMessage => ResultStrings[ResultCodeUnavailable] + :errorMessage => ResultStrings[ResultCodeUnavailable], } raise e end diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 1ac9dfd7..96e735b9 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -44,7 +44,7 @@ def open_connection(server) encryption = server[:encryption] socket_opts = { - connect_timeout: server[:connect_timeout] || DefaultConnectTimeout + connect_timeout: server[:connect_timeout] || DefaultConnectTimeout, } errors = [] @@ -133,7 +133,7 @@ def setup_encryption(args) when :start_tls message_id = next_msgid request = [ - Net::LDAP::StartTlsOid.to_ber_contextspecific(0) + Net::LDAP::StartTlsOid.to_ber_contextspecific(0), ].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) write(request, nil, message_id) @@ -283,7 +283,7 @@ def encode_sort_controls(sort_definitions) sort_control = [ Net::LDAP::LDAPControls::SORT_REQUEST.to_ber, false.to_ber, - sort_control_values.to_ber_sequence.to_s.to_ber + sort_control_values.to_ber_sequence.to_s.to_ber, ].to_ber_sequence end @@ -396,7 +396,7 @@ def search(args = nil) time.to_ber, attrs_only.to_ber, filter.to_ber, - ber_attrs.to_ber_sequence + ber_attrs.to_ber_sequence, ].to_ber_appsequence(Net::LDAP::PDU::SearchRequest) # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory @@ -409,7 +409,7 @@ def search(args = nil) Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber, # Criticality MUST be false to interoperate with normal LDAPs. false.to_ber, - rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber + rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber, ].to_ber_sequence if paged controls << ber_sort if ber_sort controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) @@ -503,7 +503,7 @@ def search(args = nil) MODIFY_OPERATIONS = { #:nodoc: :add => 0, :delete => 1, - :replace => 2 + :replace => 2, } def self.modify_ops(operations) @@ -535,7 +535,7 @@ def modify(args) message_id = next_msgid request = [ modify_dn.to_ber, - ops.to_ber_sequence + ops.to_ber_sequence, ].to_ber_appsequence(Net::LDAP::PDU::ModifyRequest) write(request, nil, message_id) diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 5527c1df..382c7acb 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -175,7 +175,7 @@ def parse_ldap_result(sequence) @ldap_result = { :resultCode => sequence[0], :matchedDN => sequence[1], - :errorMessage => sequence[2] + :errorMessage => sequence[2], } parse_search_referral(sequence[3]) if @ldap_result[:resultCode] == Net::LDAP::ResultCodeReferral end @@ -198,7 +198,7 @@ def parse_extended_response(sequence) @ldap_result = { :resultCode => sequence[0], :matchedDN => sequence[1], - :errorMessage => sequence[2] + :errorMessage => sequence[2], } @extended_response = sequence[3] end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 0fb99baf..258e8060 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -12,7 +12,7 @@ class SNMP 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2) 3 => :integer # TimeTicks32, (RFC2578 sec 2) }, - :constructed => {} + :constructed => {}, }, :context_specific => { :primitive => {}, @@ -20,8 +20,8 @@ class SNMP 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2) 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3) 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4) - } - } + }, + }, }) # SNMP 32-bit counter. @@ -70,7 +70,7 @@ class Error < StandardError; end :get_next_request, :get_response, :set_request, - :trap + :trap, ] ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1 0 => "noError", @@ -78,7 +78,7 @@ class Error < StandardError; end 2 => "noSuchName", 3 => "badValue", 4 => "readOnly", - 5 => "genErr" + 5 => "genErr", } class << self @@ -229,8 +229,8 @@ def pdu_to_ber_string [ @variables.map do|n, v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - end - ].to_ber_sequence + end, + ].to_ber_sequence, ].to_ber_contextspecific(0) when :get_next_request [ @@ -240,8 +240,8 @@ def pdu_to_ber_string [ @variables.map do|n, v| [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - end - ].to_ber_sequence + end, + ].to_ber_sequence, ].to_ber_contextspecific(1) when :get_response [ @@ -251,8 +251,8 @@ def pdu_to_ber_string [ @variables.map do|n, v| [n.to_ber_oid, v.to_ber].to_ber_sequence - end - ].to_ber_sequence + end, + ].to_ber_sequence, ].to_ber_contextspecific(2) else raise Error.new( "unknown pdu-type: #{pdu_type}" ) diff --git a/test/integration/test_add.rb b/test/integration/test_add.rb index 3cddb18a..dcac6149 100644 --- a/test/integration/test_add.rb +++ b/test/integration/test_add.rb @@ -14,7 +14,7 @@ def test_add uid: "added-user1", cn: "added-user1", sn: "added-user1", - mail: "added-user1@rubyldap.com" + mail: "added-user1@rubyldap.com", } assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect diff --git a/test/integration/test_ber.rb b/test/integration/test_ber.rb index 8fb4d374..51e93334 100644 --- a/test/integration/test_ber.rb +++ b/test/integration/test_ber.rb @@ -12,7 +12,7 @@ def test_true_ber_encoding filter: "(uid=user1)", size: 1, attributes: attrs, - attributes_only: true + attributes_only: true, ).first # matches attributes we requested diff --git a/test/integration/test_delete.rb b/test/integration/test_delete.rb index 355df7b9..0cca32a9 100644 --- a/test/integration/test_delete.rb +++ b/test/integration/test_delete.rb @@ -12,7 +12,7 @@ def setup uid: "delete-user1", cn: "delete-user1", sn: "delete-user1", - mail: "delete-user1@rubyldap.com" + mail: "delete-user1@rubyldap.com", } unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect diff --git a/test/integration/test_open.rb b/test/integration/test_open.rb index 36724f5d..a7ac09da 100644 --- a/test/integration/test_open.rb +++ b/test/integration/test_open.rb @@ -63,7 +63,7 @@ def test_nested_add_with_open uid: "nested-open-added-user1", cn: "nested-open-added-user1", sn: "nested-open-added-user1", - mail: "nested-open-added-user1@rubyldap.com" + mail: "nested-open-added-user1@rubyldap.com", } @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" diff --git a/test/integration/test_password_modify.rb b/test/integration/test_password_modify.rb index 12583363..1f1c72a9 100644 --- a/test/integration/test_password_modify.rb +++ b/test/integration/test_password_modify.rb @@ -13,7 +13,7 @@ def setup cn: 'modify-password-user1', sn: 'modify-password-user1', mail: 'modify-password-user1@rubyldap.com', - userPassword: 'passworD1' + userPassword: 'passworD1', } unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect @@ -23,7 +23,7 @@ def setup @auth = { method: :simple, username: @dn, - password: 'passworD1' + password: 'passworD1', } end diff --git a/test/test_filter.rb b/test/test_filter.rb index dd4577eb..807c86dd 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -144,7 +144,7 @@ def test_ber_conversion '(:dn:2.4.8.10:=Dino)', '(cn:dn:1.2.3.4.5:=John Smith)', '(sn:dn:2.4.6.8.10:=Barbara Jones)', - '(&(sn:dn:2.4.6.8.10:=Barbara Jones))' + '(&(sn:dn:2.4.6.8.10:=Barbara Jones))', ].each_with_index do |filter_str, index| define_method "test_decode_filter_#{index}" do filter = Net::LDAP::Filter.from_rfc2254(filter_str) @@ -195,7 +195,7 @@ def test_well_known_ber_string "foo" "\\2A\\5C" "bar", "foo" "\\2a\\5c" "bar", "foo" "\\2A\\5c" "bar", - "foo" "\\2a\\5C" "bar" + "foo" "\\2a\\5C" "bar", ].each do |escaped| # unescapes escaped characters filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}") diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 85411773..6bb027ac 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -162,7 +162,7 @@ def make_message(message_id, options = {}) app_tag: Net::LDAP::PDU::SearchResult, code: Net::LDAP::ResultCodeSuccess, matched_dn: "", - error_message: "" + error_message: "", }.merge(options) result = Net::BER::BerIdentifiedArray.new([options[:code], options[:matched_dn], options[:error_message]]) result.ber_identifier = options[:app_tag] @@ -257,7 +257,7 @@ def test_queued_read_rename assert result = conn.rename( olddn: "uid=renamable-user1,ou=People,dc=rubyldap,dc=com", - newrdn: "uid=renamed-user1" + newrdn: "uid=renamed-user1", ) assert result.success? assert_equal 2, result.message_id @@ -463,7 +463,7 @@ def test_search_net_ldap_connection_event # search data search_data_ber = Net::BER::BerIdentifiedArray.new([1, [ "uid=user1,ou=People,dc=rubyldap,dc=com", - [["uid", ["user1"]]] + [["uid", ["user1"]]], ]]) search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData search_data = [1, search_data_ber] diff --git a/testserver/ldapserver.rb b/testserver/ldapserver.rb index 25e38799..eb0c40d3 100644 --- a/testserver/ldapserver.rb +++ b/testserver/ldapserver.rb @@ -24,7 +24,7 @@ module LdapServer }, :primitive => { 2 => :string, # ldapsearch sends this to unbind - } + }, }, :context_specific => { :primitive => { @@ -34,7 +34,7 @@ module LdapServer :constructed => { 3 => :array # equality filter }, - } + }, } def post_init From 27813f51d7f4567c08e3c9b0a2e0f0c4c772b6cd Mon Sep 17 00:00:00 2001 From: Jesper Josefsson Date: Sat, 23 Jan 2016 10:48:38 +0100 Subject: [PATCH 431/435] Docs: Net::LDAP now requires ruby >= 2 --- README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index b7f6b311..53e2d468 100644 --- a/README.rdoc +++ b/README.rdoc @@ -25,7 +25,7 @@ See Net::LDAP for documentation and usage samples. == Requirements -Net::LDAP requires a Ruby 1.9.3 compatible interpreter or better. +Net::LDAP requires a Ruby 2.0.0 compatible interpreter or better. == Install From 8aaa96b552bcbd559ec6bd88846ccbba7b589db9 Mon Sep 17 00:00:00 2001 From: Ryan Showalter Date: Tue, 26 Jan 2016 18:33:28 -0600 Subject: [PATCH 432/435] Normalize the encryption parameter passed to the LDAP constructor --- lib/net/ldap.rb | 23 +++++++++++++++-------- test/test_ldap.rb | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index a9c843e7..4ba27339 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -539,7 +539,7 @@ def initialize(args = {}) @auth = args[:auth] || DefaultAuth @base = args[:base] || DefaultTreebase @force_no_page = args[:force_no_page] || DefaultForceNoPage - @encryption = args[:encryption] # may be nil + @encryption = normalize_encryption(args[:encryption]) # may be nil @connect_timeout = args[:connect_timeout] if pr = @auth[:password] and pr.respond_to?(:call) @@ -609,13 +609,7 @@ def authenticate(username, password) def encryption(args) warn "Deprecation warning: please give :encryption option as a Hash to Net::LDAP.new" return if args.nil? - return @encryption = args if args.is_a? Hash - - case method = args.to_sym - when :simple_tls, :start_tls - args = { :method => method, :tls_options => {} } - end - @encryption = args + @encryption = normalize_encryption(args) end # #open takes the same parameters as #new. #open makes a network @@ -1323,4 +1317,17 @@ def new_connection } raise e end + + # Normalize encryption parameter the constructor accepts, expands a few + # convenience symbols into recognizable hashes + def normalize_encryption(args) + return if args.nil? + return args if args.is_a? Hash + + case method = args.to_sym + when :simple_tls, :start_tls + { :method => method, :tls_options => {} } + end + end + end # class LDAP diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 85325457..8d6a9a72 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -91,4 +91,24 @@ def test_encryption assert_equal enc[:method], :start_tls end + + def test_normalize_encryption_symbol + enc = @subject.send(:normalize_encryption, :start_tls) + assert_equal enc, {:method => :start_tls, :tls_options => {}} + end + + def test_normalize_encryption_nil + enc = @subject.send(:normalize_encryption, nil) + assert_equal enc, nil + end + + def test_normalize_encryption_string + enc = @subject.send(:normalize_encryption, 'start_tls') + assert_equal enc, {:method => :start_tls, :tls_options => {}} + end + + def test_normalize_encryption_hash + enc = @subject.send(:normalize_encryption, {:method => :start_tls, :tls_options => {:foo => :bar}}) + assert_equal enc, {:method => :start_tls, :tls_options => {:foo => :bar}} + end end From 60faa64211af2d3b25808a35bfef88a5af8232b1 Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Wed, 3 Feb 2016 07:54:21 -0800 Subject: [PATCH 433/435] release 0.14.0 --- History.rdoc | 17 +++++++++++++++++ lib/net/ldap/version.rb | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/History.rdoc b/History.rdoc index f6dbbc61..27444a12 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,5 +1,22 @@ +=== Net::LDAP 0.14.0 + +* Normalize the encryption parameter passed to the LDAP constructor {#264}[https://github.com/ruby-ldap/ruby-net-ldap/pull/264] +* Update Docs: Net::LDAP now requires ruby >= 2 {#261}[https://github.com/ruby-ldap/ruby-net-ldap/pull/261] +* fix symbol proc {#255}[https://github.com/ruby-ldap/ruby-net-ldap/pull/255] +* fix trailing commas {#256}[https://github.com/ruby-ldap/ruby-net-ldap/pull/256] +* fix deprecated hash methods {#254}[https://github.com/ruby-ldap/ruby-net-ldap/pull/254] +* fix space after comma {#253}[https://github.com/ruby-ldap/ruby-net-ldap/pull/253] +* fix space inside brackets {#252}[https://github.com/ruby-ldap/ruby-net-ldap/pull/252] +* Rubocop style fixes {#249}[https://github.com/ruby-ldap/ruby-net-ldap/pull/249] +* Lazy initialize Net::LDAP::Connection's internal socket {#235}[https://github.com/ruby-ldap/ruby-net-ldap/pull/235] +* Support for rfc3062 Password Modify, closes #163 {#178}[https://github.com/ruby-ldap/ruby-net-ldap/pull/178] + === Net::LDAP 0.13.0 +Avoid this release for because of an backwards incompatibility in how encryption +is initialized https://github.com/ruby-ldap/ruby-net-ldap/pull/264. We did not +yank it because people have already worked around it. + * Set a connect_timeout for the creation of a socket {#243}[https://github.com/ruby-ldap/ruby-net-ldap/pull/243] * Update bundler before installing gems with bundler {#245}[https://github.com/ruby-ldap/ruby-net-ldap/pull/245] * Net::LDAP#encryption accepts string {#239}[https://github.com/ruby-ldap/ruby-net-ldap/pull/239] diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 259355b2..3aa9482a 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.13.0" + VERSION = "0.14.0" end end From 3bf849d415a691b5632f2e20cc637e377b15b2ad Mon Sep 17 00:00:00 2001 From: Jerry Cheung Date: Thu, 4 Feb 2016 21:47:20 -0800 Subject: [PATCH 434/435] Release 0.14.0 From 61c0936c11fc895778977f9022b2b5f9233a3370 Mon Sep 17 00:00:00 2001 From: Shreyas Date: Tue, 20 Sep 2016 16:13:42 -0700 Subject: [PATCH 435/435] Update sasl.rb --- lib/net/ldap/auth_adapter/sasl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/ldap/auth_adapter/sasl.rb b/lib/net/ldap/auth_adapter/sasl.rb index ebbe4e63..65fb6557 100644 --- a/lib/net/ldap/auth_adapter/sasl.rb +++ b/lib/net/ldap/auth_adapter/sasl.rb @@ -47,7 +47,7 @@ def bind(auth) end return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress - raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) + raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > 10) cred = chall.call(pdu.result_server_sasl_creds) end