From 1509aa8ef61496b50ac5a3545f2061b9d12cbf17 Mon Sep 17 00:00:00 2001 From: Kaspar Schiess Date: Fri, 12 Feb 2010 14:39:57 +0100 Subject: [PATCH] ! Fixes all tests Some code has been removed. Version control is not synonymous with code storage - if you're not using it now, you probably don't have working tests and the code will be buggy anyway. Write it when you need it. --- lib/net/ber.rb | 12 +-- lib/net/ber/ber_parser.rb | 17 +--- lib/net/ldap/core_ext/all.rb | 4 +- lib/net/ldap/core_ext/array.rb | 2 +- lib/net/ldap/core_ext/bignum.rb | 33 +++---- lib/net/ldap/core_ext/fixnum.rb | 38 ++++++--- lib/net/ldap/core_ext/string.rb | 15 +--- lib/net/ldap/filter.rb | 6 +- lib/net/ldap/psw.rb | 2 +- spec/integration/ssl_ber_spec.rb | 33 +++++++ spec/spec.opts | 2 + spec/spec_helper.rb | 1 + spec/unit/ber/ber_spec.rb | 18 ++++ test/test_ber.rb | 142 +++++++++++++------------------ test/test_filter.rb | 2 +- testserver/ldapserver.rb | 3 - 16 files changed, 164 insertions(+), 166 deletions(-) create mode 100644 spec/integration/ssl_ber_spec.rb create mode 100644 spec/spec.opts create mode 100644 spec/spec_helper.rb create mode 100644 spec/unit/ber/ber_spec.rb diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 8fe8caf..0b0ce03 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -77,7 +77,7 @@ module Net class BerIdentifiedArray < Array attr_accessor :ber_identifier - def initialize + def initialize(*args) super end end @@ -88,16 +88,6 @@ module Net "\005\000" end end - - class BerIdentifiedOid - attr_accessor :ber_identifier - def initialize oid - if oid.is_a?(String) - oid = oid.split(/\./).map {|s| s.to_i } - end - @value = oid - end - end end end diff --git a/lib/net/ber/ber_parser.rb b/lib/net/ber/ber_parser.rb index 241ddca..8ba5a2b 100644 --- a/lib/net/ber/ber_parser.rb +++ b/lib/net/ber/ber_parser.rb @@ -33,19 +33,10 @@ module Net # packets coming from streams that don't block when # we ask for more data (like StringIOs). At it is, # this can throw TypeErrors and other nasties. - - # We might have been included in two kinds of things: IO-like - # (answering to getbyte) and String-like (answering to to_s). Have - # stream be a stream that is IO-like in both cases. - if respond_to? :getbyte - stream = self - else - stream = StringIO.new(self.to_s) - end - - id = stream.getbyte or return nil # don't trash this value, we'll use it later + + id = getbyte or return nil # don't trash this value, we'll use it later - n = stream.getbyte + n = getbyte lengthlength,contentlength = if n <= 127 [1,n] else @@ -56,7 +47,7 @@ module Net [1 + (n & 127), j] end - newobj = stream.read contentlength + newobj = read contentlength # This exceptionally clever and clear bit of code is verrrry slow. objtype = (syntax && syntax[id]) || BuiltinSyntax[id] diff --git a/lib/net/ldap/core_ext/all.rb b/lib/net/ldap/core_ext/all.rb index 5be52e5..3aa1ba6 100644 --- a/lib/net/ldap/core_ext/all.rb +++ b/lib/net/ldap/core_ext/all.rb @@ -10,8 +10,8 @@ class Array end class String - include Net::LDAP::Extensions::String include Net::BER::BERParser + include Net::LDAP::Extensions::String end class Bignum @@ -40,4 +40,4 @@ end class OpenSSL::SSL::SSLSocket include Net::BER::BERParser -end \ No newline at end of file +end diff --git a/lib/net/ldap/core_ext/array.rb b/lib/net/ldap/core_ext/array.rb index ff88c9f..e2ad1e0 100644 --- a/lib/net/ldap/core_ext/array.rb +++ b/lib/net/ldap/core_ext/array.rb @@ -33,7 +33,7 @@ module Net private def to_ber_seq_internal code - s = self.to_s + s = self.join [code].pack('C') + s.length.to_ber_length_encoding + s end end diff --git a/lib/net/ldap/core_ext/bignum.rb b/lib/net/ldap/core_ext/bignum.rb index 6decc88..c976a85 100644 --- a/lib/net/ldap/core_ext/bignum.rb +++ b/lib/net/ldap/core_ext/bignum.rb @@ -4,32 +4,19 @@ module Net module Bignum def to_ber - #i = [self].pack('w') - #i.length > 126 and raise Net::BER::BerError.new( "range error in bignum" ) - #[2, i.length].pack("CC") + i + # 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 + result = [] - # Ruby represents Bignums as two's-complement numbers so we may actually be - # good as far as representing negatives goes. - # I'm sure this implementation can be improved performance-wise if necessary. - # Ruby's Bignum#size returns the number of bytes in the internal representation - # of the number, but it can and will include leading zero bytes on at least - # some implementations. Evidently Ruby stores these as sets of quadbytes. - # It's not illegal in BER to encode all of the leading zeroes but let's strip - # them out anyway. - # - sz = self.size - out = "\000" * sz - (sz*8).times {|bit| - if self[bit] == 1 - out[bit/8] += (1 << (bit % 8)) - end - } - - while out.length > 1 and out[-1] == 0 - out.slice!(-1,1) + n = self + while n>0 + b = n & 0xff + result << b + n = n >> 8 end - [2, out.length].pack("CC") + out.reverse + "\002" + ([result.size] + result.reverse).pack('C*') end end diff --git a/lib/net/ldap/core_ext/fixnum.rb b/lib/net/ldap/core_ext/fixnum.rb index 2a899e5..e8ba479 100644 --- a/lib/net/ldap/core_ext/fixnum.rb +++ b/lib/net/ldap/core_ext/fixnum.rb @@ -2,14 +2,23 @@ module Net class LDAP module Extensions module Fixnum + # + # to_ber + # def to_ber "\002" + to_ber_internal end + # + # to_ber_enumerated + # def to_ber_enumerated "\012" + to_ber_internal end + # + # to_ber_length_encoding + # def to_ber_length_encoding if self <= 127 [self].pack('C') @@ -29,21 +38,24 @@ module Net #-- # Called internally to BER-encode the length and content bytes of a Fixnum. # The caller will prepend the tag byte. + MAX_SIZE = 0.size def to_ber_internal - # PLEASE optimize this code path. It's awfully ugly and probably slow. - # It also doesn't understand negative numbers yet. - raise Net::BER::BerError.new( "range error in fixnum" ) unless self >= 0 - z = [self].pack("N") - zlen = if self < 0x80 - 1 - elsif self < 0x8000 - 2 - elsif self < 0x800000 - 3 - else - 4 + size = MAX_SIZE + while size>1 + break if (self & (0xff << (size-1)*8)) > 0 + size -= 1 end - [zlen].pack("C") + z[0-zlen,zlen] + + result = [size] + + while size>0 + # right shift size-1 bytes, mask with 0xff + result << ((self >> ((size-1)*8)) & 0xff) + + size -= 1 + end + + result.pack('C*') end private :to_ber_internal end diff --git a/lib/net/ldap/core_ext/string.rb b/lib/net/ldap/core_ext/string.rb index 64a7cbc..b1d170d 100644 --- a/lib/net/ldap/core_ext/string.rb +++ b/lib/net/ldap/core_ext/string.rb @@ -1,3 +1,5 @@ +require 'stringio' + module Net class LDAP module Extensions @@ -29,18 +31,9 @@ module Net end def read_ber syntax=nil - StringIO.new(self).read_ber(syntax) + StringIO.new(self). + read_ber(syntax) end - - # def read_ber! syntax=nil - # obj,n_consumed = read_ber_from_string(self, syntax) - # if n_consumed - # self.slice!(0...n_consumed) - # obj - # else - # nil - # end - # end end end end diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 63829e8..a972d71 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -1,8 +1,3 @@ -# $Id$ -# -# -#---------------------------------------------------------------------------- -# # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. # # Gmail: garbagecat10 @@ -25,6 +20,7 @@ # # +require 'strscan' module Net class LDAP diff --git a/lib/net/ldap/psw.rb b/lib/net/ldap/psw.rb index 46095c2..1c37521 100644 --- a/lib/net/ldap/psw.rb +++ b/lib/net/ldap/psw.rb @@ -43,7 +43,7 @@ module Net when :md5 [Digest::MD5.new, 'MD5'] when :sha - [Digest::SHA1.new, 'sha'] + [Digest::SHA1.new, 'SHA'] # when ssha else raise Net::LDAP::LdapError.new( "unsupported password-hash type (#{type})" ) diff --git a/spec/integration/ssl_ber_spec.rb b/spec/integration/ssl_ber_spec.rb new file mode 100644 index 0000000..33379d0 --- /dev/null +++ b/spec/integration/ssl_ber_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +require 'socket' +require 'openssl' + +require 'net/ldap' + +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 + end + + attr_reader :to, :from + before(:each) do + @from, @to = IO.pipe + + @to = Net::LDAP::SSLSocket.wrap(to) + @from = Net::LDAP::SSLSocket.wrap(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/spec/spec.opts b/spec/spec.opts new file mode 100644 index 0000000..d019bfb --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1,2 @@ +--format specdoc +--colour \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1 @@ + diff --git a/spec/unit/ber/ber_spec.rb b/spec/unit/ber/ber_spec.rb new file mode 100644 index 0000000..547f9a7 --- /dev/null +++ b/spec/unit/ber/ber_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +require 'net/ber' +require 'net/ldap' + +describe "Ber encoding of various types" do + def properly_encode_and_decode + simple_matcher('properly encode and decode') do |given| + given.to_ber.read_ber.should == given + end + end + + context "array" do + it "should properly encode []" do + [].should properly_encode_and_decode + end + end +end \ No newline at end of file diff --git a/test/test_ber.rb b/test/test_ber.rb index c5f6af1..defe969 100644 --- a/test/test_ber.rb +++ b/test/test_ber.rb @@ -1,100 +1,78 @@ -# $Id: testber.rb 230 2006-12-19 18:27:57Z blackhedd $ - +# encoding: ASCII-8BIT require 'common' class TestBer < Test::Unit::TestCase - def test_encode_boolean - assert_equal( "\x01\x01\x01", true.to_ber ) # should actually be: 01 01 ff - assert_equal( "\x01\x01\x00", false.to_ber ) - end + def test_encode_boolean + assert_equal( "\x01\x01\x01", true.to_ber ) # should actually be: 01 01 ff + assert_equal( "\x01\x01\x00", false.to_ber ) + end - #def test_encode_nil - # assert_equal( "\x05\x00", nil.to_ber ) - #end + #def test_encode_nil + # assert_equal( "\x05\x00", nil.to_ber ) + #end - def test_encode_integer + def test_encode_integer - # Fixnum - # - #assert_equal( "\x02\x02\x96\x46", -27_066.to_ber ) - #assert_equal( "\x02\x02\xFF\x7F", -129.to_ber ) - #assert_equal( "\x02\x01\x80", -128.to_ber ) - #assert_equal( "\x02\x01\xFF", -1.to_ber ) + # Fixnum + # + #assert_equal( "\x02\x02\x96\x46", -27_066.to_ber ) + #assert_equal( "\x02\x02\xFF\x7F", -129.to_ber ) + #assert_equal( "\x02\x01\x80", -128.to_ber ) + #assert_equal( "\x02\x01\xFF", -1.to_ber ) - assert_equal( "\x02\x01\x00", 0.to_ber ) - assert_equal( "\x02\x01\x01", 1.to_ber ) - assert_equal( "\x02\x01\x7F", 127.to_ber ) - assert_equal( "\x02\x02\x00\x80", 128.to_ber ) - assert_equal( "\x02\x02\x00\xFF", 255.to_ber ) + assert_equal( "\x02\x01\x00", 0.to_ber ) + assert_equal( "\x02\x01\x01", 1.to_ber ) + assert_equal( "\x02\x01\x7F", 127.to_ber ) + assert_equal( "\x02\x01\x80", 128.to_ber ) + assert_equal( "\x02\x01\xFF", 255.to_ber ) - assert_equal( "\x02\x02\x01\x00", 256.to_ber ) - assert_equal( "\x02\x03\x00\xFF\xFF", 65535.to_ber ) + assert_equal( "\x02\x02\x01\x00", 256.to_ber ) + assert_equal( "\x02\x02\xFF\xFF", 65535.to_ber ) - assert_equal( "\x02\x03\x01\x00\x00", 65536.to_ber ) - assert_equal( "\x02\x04\x00\xFF\xFF\xFF", 16_777_215.to_ber ) + assert_equal( "\x02\x03\x01\x00\x00", 65536.to_ber ) + assert_equal( "\x02\x03\xFF\xFF\xFF", 16_777_215.to_ber ) - assert_equal( "\x02\x04\x01\x00\x00\x00", 0x01000000.to_ber ) - assert_equal( "\x02\x04\x3F\xFF\xFF\xFF", 0x3FFFFFFF.to_ber ) + assert_equal( "\x02\x04\x01\x00\x00\x00", 0x01000000.to_ber ) + assert_equal( "\x02\x04\x3F\xFF\xFF\xFF", 0x3FFFFFFF.to_ber ) - # Bignum - # - assert_equal( "\x02\x04\x4F\xFF\xFF\xFF", 0x4FFFFFFF.to_ber ) - #assert_equal( "\x02\x05\x00\xFF\xFF\xFF\xFF", 0xFFFFFFFF.to_ber ) - end + # Bignum + # + assert_equal( "\x02\x04\x4F\xFF\xFF\xFF", 0x4FFFFFFF.to_ber ) + #assert_equal( "\x02\x05\x00\xFF\xFF\xFF\xFF", 0xFFFFFFFF.to_ber ) + end - # TOD Add some much bigger numbers - # 5000000000 is a Bignum, which hits different code. - def test_ber_integers - assert_equal( "\002\001\005", 5.to_ber ) - assert_equal( "\002\002\001\364", 500.to_ber ) - assert_equal( "\002\003\0\303P", 50000.to_ber ) - assert_equal( "\002\005\001*\005\362\000", 5000000000.to_ber ) - end + # TOD Add some much bigger numbers + # 5000000000 is a Bignum, which hits different code. + def test_ber_integers + assert_equal( "\002\001\005", 5.to_ber ) + assert_equal( "\002\002\001\364", 500.to_ber ) + assert_equal( "\x02\x02\xC3P", 50000.to_ber ) + assert_equal( "\002\005\001*\005\362\000", 5000000000.to_ber ) + end - def test_ber_bignums - # Some of these values are Fixnums and some are Bignums. Different BER code. - [ - 5, - 50, - 500, - 5000, - 50000, - 500000, - 5000000, - 50000000, - 500000000, - 1000000000, - 2000000000, - 3000000000, - 4000000000, - 5000000000 - ].each {|val| - assert_equal( val, val.to_ber.read_ber ) - } - end + def test_ber_bignums + # Some of these values are Fixnums and some are Bignums. Different BER code. + 100.times do |p| + n = 2 << p + assert_equal(n, n.to_ber.read_ber, "2**#{p} could not be read back") + + n = 5 * 10**p + assert_equal(n, n.to_ber.read_ber) + end + end - def test_ber_parsing - assert_equal( 6, "\002\001\006".read_ber( Net::LDAP::AsnSyntax )) - assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax )) - end + def test_ber_parsing + assert_equal( 6, "\002\001\006".read_ber( Net::LDAP::AsnSyntax )) + assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax )) + end - def test_ber_parser_on_ldap_bind_request - require 'stringio' + def test_ber_parser_on_ldap_bind_request + s = StringIO.new( + "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" ) - s = StringIO.new( - "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" ) - - assert_equal( - [1, [3, "Administrator", "ad_is_bogus"]], - s.read_ber( Net::LDAP::AsnSyntax )) - end - - def test_oid - oid = Net::BER::BerIdentifiedOid.new( [1,3,6,1,2,1,1,1,0] ) - assert_equal( "\006\b+\006\001\002\001\001\001\000", oid.to_ber ) - - oid = Net::BER::BerIdentifiedOid.new( "1.3.6.1.2.1.1.1.0" ) - assert_equal( "\006\b+\006\001\002\001\001\001\000", oid.to_ber ) - end + assert_equal( + [1, [3, "Administrator", "ad_is_bogus"]], + s.read_ber( Net::LDAP::AsnSyntax )) + end end diff --git a/test/test_filter.rb b/test/test_filter.rb index 08b4f30..f1ed747 100644 --- a/test/test_filter.rb +++ b/test/test_filter.rb @@ -74,7 +74,7 @@ class TestFilter < Test::Unit::TestCase Net::LDAP::Filter.construct("objectclass=aaa*bbb*"), Net::LDAP::Filter.construct("objectclass=aaa*bbb*ccc*"), ].each {|ber| - f = Net::LDAP::Filter.parse_ber( ber.to_ber.read_ber( Net::LDAP::AsnSyntax) ) + f = Net::LDAP::Filter.parse_ber( ber.to_ber.read_ber( Net::LDAP::AsnSyntax) ) assert( f == ber ) assert_equal( f.to_ber, ber.to_ber ) } diff --git a/testserver/ldapserver.rb b/testserver/ldapserver.rb index d05f03f..eba130c 100644 --- a/testserver/ldapserver.rb +++ b/testserver/ldapserver.rb @@ -12,9 +12,6 @@ # reactor library. # - -require 'stringio' - #------------------------------------------------ module LdapServer