net-ldap-1 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.autotest +11 -0
  2. data/.rspec +2 -0
  3. data/Contributors.rdoc +21 -0
  4. data/Hacking.rdoc +68 -0
  5. data/History.rdoc +186 -0
  6. data/License.rdoc +29 -0
  7. data/Manifest.txt +49 -0
  8. data/README.rdoc +52 -0
  9. data/Rakefile +74 -0
  10. data/autotest/discover.rb +1 -0
  11. data/lib/net-ldap.rb +2 -0
  12. data/lib/net/ber.rb +318 -0
  13. data/lib/net/ber/ber_parser.rb +168 -0
  14. data/lib/net/ber/core_ext.rb +62 -0
  15. data/lib/net/ber/core_ext/array.rb +96 -0
  16. data/lib/net/ber/core_ext/bignum.rb +22 -0
  17. data/lib/net/ber/core_ext/false_class.rb +10 -0
  18. data/lib/net/ber/core_ext/fixnum.rb +66 -0
  19. data/lib/net/ber/core_ext/string.rb +65 -0
  20. data/lib/net/ber/core_ext/true_class.rb +12 -0
  21. data/lib/net/ldap.rb +1618 -0
  22. data/lib/net/ldap/dataset.rb +154 -0
  23. data/lib/net/ldap/dn.rb +225 -0
  24. data/lib/net/ldap/entry.rb +185 -0
  25. data/lib/net/ldap/filter.rb +759 -0
  26. data/lib/net/ldap/password.rb +31 -0
  27. data/lib/net/ldap/pdu.rb +273 -0
  28. data/lib/net/snmp.rb +268 -0
  29. data/net-ldap-1.gemspec +58 -0
  30. data/spec/integration/ssl_ber_spec.rb +36 -0
  31. data/spec/spec.opts +2 -0
  32. data/spec/spec_helper.rb +5 -0
  33. data/spec/unit/ber/ber_spec.rb +109 -0
  34. data/spec/unit/ber/core_ext/string_spec.rb +51 -0
  35. data/spec/unit/ldap/dn_spec.rb +80 -0
  36. data/spec/unit/ldap/entry_spec.rb +51 -0
  37. data/spec/unit/ldap/filter_spec.rb +84 -0
  38. data/spec/unit/ldap_spec.rb +78 -0
  39. data/test/common.rb +3 -0
  40. data/test/test_entry.rb +59 -0
  41. data/test/test_filter.rb +122 -0
  42. data/test/test_ldap_connection.rb +24 -0
  43. data/test/test_ldif.rb +79 -0
  44. data/test/test_password.rb +17 -0
  45. data/test/test_rename.rb +77 -0
  46. data/test/test_snmp.rb +114 -0
  47. data/test/testdata.ldif +101 -0
  48. data/testserver/ldapserver.rb +210 -0
  49. data/testserver/testdata.ldif +101 -0
  50. metadata +197 -0
@@ -0,0 +1,58 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |s|
3
+ s.name = %q{net-ldap-1}
4
+ s.version = "0.4.0"
5
+
6
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
+ s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler"]
8
+ s.date = %q{2012-02-28}
9
+ s.description = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the
10
+ Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for
11
+ accessing distributed directory services. Net::LDAP is written completely in
12
+ Ruby with no external dependencies. It supports most LDAP client features and a
13
+ subset of server features as well.
14
+
15
+ Net::LDAP has been tested against modern popular LDAP servers including
16
+ OpenLDAP and Active Directory. The current release is mostly compliant with
17
+ earlier versions of the IETF LDAP RFCs (2251–2256, 2829–2830, 3377, and 3771).
18
+ Our roadmap for Net::LDAP 1.0 is to gain full <em>client</em> compliance with
19
+ the most recent LDAP RFCs (4510–4519, plutions of 4520–4532).}
20
+ s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"]
21
+ s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"]
22
+ 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-1.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"]
23
+ s.homepage = %q{http://github.com.org/ruby-ldap/ruby-net-ldap}
24
+ s.rdoc_options = ["--main", "README.rdoc"]
25
+ s.require_paths = ["lib"]
26
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
27
+ s.rubyforge_project = %q{net-ldap}
28
+ s.rubygems_version = %q{1.5.2}
29
+ 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}
30
+ 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"]
31
+
32
+ if s.respond_to? :specification_version then
33
+ s.specification_version = 3
34
+
35
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
36
+ s.add_development_dependency(%q<hoe-git>, ["~> 1"])
37
+ s.add_development_dependency(%q<hoe-gemspec>, ["~> 1"])
38
+ s.add_development_dependency(%q<metaid>, ["~> 1"])
39
+ s.add_development_dependency(%q<flexmock>, ["~> 0.9.0"])
40
+ s.add_development_dependency(%q<rspec>, ["~> 2.0"])
41
+ s.add_development_dependency(%q<hoe>, [">= 2.9.1"])
42
+ else
43
+ s.add_dependency(%q<hoe-git>, ["~> 1"])
44
+ s.add_dependency(%q<hoe-gemspec>, ["~> 1"])
45
+ s.add_dependency(%q<metaid>, ["~> 1"])
46
+ s.add_dependency(%q<flexmock>, ["~> 0.9.0"])
47
+ s.add_dependency(%q<rspec>, ["~> 2.0"])
48
+ s.add_dependency(%q<hoe>, [">= 2.9.1"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<hoe-git>, ["~> 1"])
52
+ s.add_dependency(%q<hoe-gemspec>, ["~> 1"])
53
+ s.add_dependency(%q<metaid>, ["~> 1"])
54
+ s.add_dependency(%q<flexmock>, ["~> 0.9.0"])
55
+ s.add_dependency(%q<rspec>, ["~> 2.0"])
56
+ s.add_dependency(%q<hoe>, [">= 2.9.1"])
57
+ end
58
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ require 'net/ldap'
4
+
5
+ describe "BER serialisation (SSL)" do
6
+ # Transmits str to #to and reads it back from #from.
7
+ #
8
+ def transmit(str)
9
+ to.write(str)
10
+ to.close
11
+
12
+ from.read
13
+ end
14
+
15
+ attr_reader :to, :from
16
+ before(:each) do
17
+ @from, @to = IO.pipe
18
+
19
+ # The production code operates on sockets, which do need #connect called
20
+ # on them to work. Pipes are more robust for this test, so we'll skip
21
+ # the #connect call since it fails.
22
+ flexmock(OpenSSL::SSL::SSLSocket).
23
+ new_instances.should_receive(:connect => nil)
24
+
25
+ @to = Net::LDAP::Connection.wrap_with_ssl(to)
26
+ @from = Net::LDAP::Connection.wrap_with_ssl(from)
27
+ end
28
+
29
+ it "should transmit strings" do
30
+ transmit('foo').should == 'foo'
31
+ end
32
+ it "should correctly transmit numbers" do
33
+ to.write 1234.to_ber
34
+ from.read_ber.should == 1234
35
+ end
36
+ end
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,5 @@
1
+ require 'net/ldap'
2
+
3
+ RSpec.configure do |config|
4
+ config.mock_with :flexmock
5
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ require 'net/ber'
4
+ require 'net/ldap'
5
+
6
+ describe "BER encoding of" do
7
+
8
+ RSpec::Matchers.define :properly_encode_and_decode do
9
+ match do |given|
10
+ given.to_ber.read_ber.should == given
11
+ end
12
+ end
13
+
14
+ context "arrays" do
15
+ it "should properly encode/decode []" do
16
+ [].should properly_encode_and_decode
17
+ end
18
+ it "should properly encode/decode [1,2,3]" do
19
+ ary = [1,2,3]
20
+ encoded_ary = ary.map { |el| el.to_ber }.to_ber
21
+
22
+ encoded_ary.read_ber.should == ary
23
+ end
24
+ end
25
+ context "booleans" do
26
+ it "should encode true" do
27
+ true.to_ber.should == "\x01\x01\x01"
28
+ end
29
+ it "should encode false" do
30
+ false.to_ber.should == "\x01\x01\x00"
31
+ end
32
+ end
33
+ context "numbers" do
34
+ # Sample based
35
+ {
36
+ 0 => "\x02\x01\x00",
37
+ 1 => "\x02\x01\x01",
38
+ 127 => "\x02\x01\x7F",
39
+ 128 => "\x02\x01\x80",
40
+ 255 => "\x02\x01\xFF",
41
+ 256 => "\x02\x02\x01\x00",
42
+ 65535 => "\x02\x02\xFF\xFF",
43
+ 65536 => "\x02\x03\x01\x00\x00",
44
+ 16_777_215 => "\x02\x03\xFF\xFF\xFF",
45
+ 0x01000000 => "\x02\x04\x01\x00\x00\x00",
46
+ 0x3FFFFFFF => "\x02\x04\x3F\xFF\xFF\xFF",
47
+ 0x4FFFFFFF => "\x02\x04\x4F\xFF\xFF\xFF",
48
+
49
+ # Some odd samples...
50
+ 5 => "\002\001\005",
51
+ 500 => "\002\002\001\364",
52
+ 50_000 => "\x02\x02\xC3P",
53
+ 5_000_000_000 => "\002\005\001*\005\362\000"
54
+ }.each do |number, expected_encoding|
55
+ it "should encode #{number} as #{expected_encoding.inspect}" do
56
+ number.to_ber.should == expected_encoding
57
+ end
58
+ end
59
+
60
+ # Round-trip encoding: This is mostly to be sure to cover Bignums well.
61
+ context "when decoding with #read_ber" do
62
+ it "should correctly handle powers of two" do
63
+ 100.times do |p|
64
+ n = 2 << p
65
+
66
+ n.should properly_encode_and_decode
67
+ end
68
+ end
69
+ it "should correctly handle powers of ten" do
70
+ 100.times do |p|
71
+ n = 5 * 10**p
72
+
73
+ n.should properly_encode_and_decode
74
+ end
75
+ end
76
+ end
77
+ end
78
+ if "Ruby 1.9".respond_to?(:encoding)
79
+ context "strings" do
80
+ it "should properly encode UTF-8 strings" do
81
+ "\u00e5".force_encoding("UTF-8").to_ber.should ==
82
+ "\x04\x02\xC3\xA5"
83
+ end
84
+ it "should properly encode strings encodable as UTF-8" do
85
+ "teststring".encode("US-ASCII").to_ber.should == "\x04\nteststring"
86
+ end
87
+ it "should fail on strings that can not be converted to UTF-8" do
88
+ error = Encoding::UndefinedConversionError
89
+ lambda {"\x81".to_ber }.should raise_exception(error)
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "BER decoding of" do
96
+ context "numbers" do
97
+ it "should decode #{"\002\001\006".inspect} (6)" do
98
+ "\002\001\006".read_ber(Net::LDAP::AsnSyntax).should == 6
99
+ end
100
+ it "should decode #{"\004\007testing".inspect} ('testing')" do
101
+ "\004\007testing".read_ber(Net::LDAP::AsnSyntax).should == 'testing'
102
+ end
103
+ it "should decode an ldap bind request" do
104
+ "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus".
105
+ read_ber(Net::LDAP::AsnSyntax).should ==
106
+ [1, [3, "Administrator", "ad_is_bogus"]]
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'metaid'
3
+
4
+ describe String, "when extended with BER core extensions" do
5
+ describe "<- #read_ber! (consuming read_ber method)" do
6
+ context "when passed an ldap bind request and some extra data" do
7
+ attr_reader :str, :result
8
+ before(:each) do
9
+ @str = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED"
10
+ @result = str.read_ber!(Net::LDAP::AsnSyntax)
11
+ end
12
+
13
+ it "should correctly parse the ber message" do
14
+ result.should == [1, [3, "Administrator", "ad_is_bogus"]]
15
+ end
16
+ it "should leave unconsumed part of message in place" do
17
+ str.should == " UNCONSUMED"
18
+ end
19
+
20
+ context "if an exception occurs during #read_ber" do
21
+ attr_reader :initial_value
22
+ before(:each) do
23
+ stub_exception_class = Class.new(StandardError)
24
+
25
+ @initial_value = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus"
26
+ @str = initial_value.dup
27
+
28
+ # Defines a string
29
+ io = StringIO.new(initial_value)
30
+ io.meta_def :read_ber do |syntax|
31
+ read
32
+ raise stub_exception_class
33
+ end
34
+ flexmock(StringIO).should_receive(:new).and_return(io)
35
+
36
+ begin
37
+ str.read_ber!(Net::LDAP::AsnSyntax)
38
+ rescue stub_exception_class
39
+ # EMPTY ON PURPOSE
40
+ else
41
+ raise "The stub code should raise an exception!"
42
+ end
43
+ end
44
+
45
+ it "should not modify string" do
46
+ str.should == initial_value
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+ require 'net/ldap/dn'
3
+
4
+ describe Net::LDAP::DN do
5
+ describe "<- .construct" do
6
+ attr_reader :dn
7
+
8
+ before(:each) do
9
+ @dn = Net::LDAP::DN.new('cn', ',+"\\<>;', 'ou=company')
10
+ end
11
+
12
+ it "should construct a Net::LDAP::DN" do
13
+ dn.should be_an_instance_of(Net::LDAP::DN)
14
+ end
15
+
16
+ it "should escape all the required characters" do
17
+ dn.to_s.should == 'cn=\\,\\+\\"\\\\\\<\\>\\;,ou=company'
18
+ end
19
+ end
20
+
21
+ describe "<- .to_a" do
22
+ context "parsing" do
23
+ {
24
+ 'cn=James, ou=Company\\,\\20LLC' => ['cn','James','ou','Company, LLC'],
25
+ 'cn = \ James , ou = "Comp\28ny" ' => ['cn',' James','ou','Comp(ny'],
26
+ '1.23.4= #A3B4D5 ,ou=Company' => ['1.23.4','#A3B4D5','ou','Company'],
27
+ }.each do |key, value|
28
+ context "(#{key})" do
29
+ attr_reader :dn
30
+
31
+ before(:each) do
32
+ @dn = Net::LDAP::DN.new(key)
33
+ end
34
+
35
+ it "should decode into a Net::LDAP::DN" do
36
+ dn.should be_an_instance_of(Net::LDAP::DN)
37
+ end
38
+
39
+ it "should return the correct array" do
40
+ dn.to_a.should == value
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ context "parsing bad input" do
47
+ [
48
+ 'cn=James,',
49
+ 'cn=#aa aa',
50
+ 'cn="James',
51
+ 'cn=J\ames',
52
+ 'cn=\\',
53
+ '1.2.d=Value',
54
+ 'd1.2=Value',
55
+ ].each do |value|
56
+ context "(#{value})" do
57
+ attr_reader :dn
58
+
59
+ before(:each) do
60
+ @dn = Net::LDAP::DN.new(value)
61
+ end
62
+
63
+ it "should decode into a Net::LDAP::DN" do
64
+ dn.should be_an_instance_of(Net::LDAP::DN)
65
+ end
66
+
67
+ it "should raise an error on parsing" do
68
+ lambda { dn.to_a }.should raise_error
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "<- .escape(str)" do
76
+ it "should escape ,, +, \", \\, <, >, and ;" do
77
+ Net::LDAP::DN.escape(',+"\\<>;').should == '\\,\\+\\"\\\\\\<\\>\\;'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::LDAP::Entry do
4
+ attr_reader :entry
5
+ before(:each) do
6
+ @entry = Net::LDAP::Entry.from_single_ldif_string(
7
+ %Q{dn: something
8
+ foo: foo
9
+ barAttribute: bar
10
+ }
11
+ )
12
+ end
13
+
14
+ describe "entry access" do
15
+ it "should always respond to #dn" do
16
+ entry.should respond_to(:dn)
17
+ end
18
+
19
+ context "<- #foo" do
20
+ it "should respond_to?" do
21
+ entry.should respond_to(:foo)
22
+ end
23
+ it "should return 'foo'" do
24
+ entry.foo.should == ['foo']
25
+ end
26
+ end
27
+ context "<- #Foo" do
28
+ it "should respond_to?" do
29
+ entry.should respond_to(:Foo)
30
+ end
31
+ it "should return 'foo'" do
32
+ entry.foo.should == ['foo']
33
+ end
34
+ end
35
+ context "<- #foo=" do
36
+ it "should respond_to?" do
37
+ entry.should respond_to(:foo=)
38
+ end
39
+ it "should set 'foo'" do
40
+ entry.foo= 'bar'
41
+ entry.foo.should == ['bar']
42
+ end
43
+ end
44
+ context "<- #fOo=" do
45
+ it "should return 'foo'" do
46
+ entry.fOo= 'bar'
47
+ entry.fOo.should == ['bar']
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::LDAP::Filter do
4
+ describe "<- .ex(attr, value)" do
5
+ context "('foo', 'bar')" do
6
+ attr_reader :filter
7
+ before(:each) do
8
+ @filter = Net::LDAP::Filter.ex('foo', 'bar')
9
+ end
10
+ it "should convert to 'foo:=bar'" do
11
+ filter.to_s.should == '(foo:=bar)'
12
+ end
13
+ it "should survive roundtrip via to_s/from_rfc2254" do
14
+ Net::LDAP::Filter.from_rfc2254(filter.to_s).should == filter
15
+ end
16
+ it "should survive roundtrip conversion to/from ber" do
17
+ ber = filter.to_ber
18
+ Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
19
+ filter
20
+ end
21
+ end
22
+ context "various legal inputs" do
23
+ [
24
+ '(o:dn:=Ace Industry)',
25
+ '(:dn:2.4.8.10:=Dino)',
26
+ '(cn:dn:1.2.3.4.5:=John Smith)',
27
+ '(sn:dn:2.4.6.8.10:=Barbara Jones)',
28
+ '(&(sn:dn:2.4.6.8.10:=Barbara Jones))'
29
+ ].each do |filter_str|
30
+ context "from_rfc2254(#{filter_str.inspect})" do
31
+ attr_reader :filter
32
+ before(:each) do
33
+ @filter = Net::LDAP::Filter.from_rfc2254(filter_str)
34
+ end
35
+
36
+ it "should decode into a Net::LDAP::Filter" do
37
+ filter.should be_an_instance_of(Net::LDAP::Filter)
38
+ end
39
+ it "should survive roundtrip conversion to/from ber" do
40
+ ber = filter.to_ber
41
+ Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
42
+ filter
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ describe "<- .construct" do
49
+ it "should accept apostrophes in filters (regression)" do
50
+ Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)"
51
+ end
52
+ end
53
+
54
+ describe "convenience filter constructors" do
55
+ def eq(attribute, value)
56
+ described_class.eq(attribute, value)
57
+ end
58
+ describe "<- .equals(attr, val)" do
59
+ it "should delegate to .eq with escaping" do
60
+ described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo')
61
+ end
62
+ end
63
+ describe "<- .begins(attr, val)" do
64
+ it "should delegate to .eq with escaping" do
65
+ described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*')
66
+ end
67
+ end
68
+ describe "<- .ends(attr, val)" do
69
+ it "should delegate to .eq with escaping" do
70
+ described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo')
71
+ end
72
+ end
73
+ describe "<- .contains(attr, val)" do
74
+ it "should delegate to .eq with escaping" do
75
+ described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*')
76
+ end
77
+ end
78
+ end
79
+ describe "<- .escape(str)" do
80
+ it "should escape nul, *, (, ) and \\" do
81
+ Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C"
82
+ end
83
+ end
84
+ end