socialcast-net-ldap 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemtest +0 -0
- data/COPYING +272 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +29 -0
- data/Hacking.rdoc +16 -0
- data/History.txt +137 -0
- data/LICENSE +56 -0
- data/Manifest.txt +45 -0
- data/README.txt +70 -0
- data/Rakefile +124 -0
- data/lib/net-ldap.rb +1 -0
- data/lib/net/ber.rb +341 -0
- data/lib/net/ber/ber_parser.rb +168 -0
- data/lib/net/ber/core_ext.rb +72 -0
- data/lib/net/ber/core_ext/array.rb +79 -0
- data/lib/net/ber/core_ext/bignum.rb +19 -0
- data/lib/net/ber/core_ext/false_class.rb +7 -0
- data/lib/net/ber/core_ext/fixnum.rb +63 -0
- data/lib/net/ber/core_ext/string.rb +57 -0
- data/lib/net/ber/core_ext/true_class.rb +9 -0
- data/lib/net/ldap.rb +1539 -0
- data/lib/net/ldap/dataset.rb +174 -0
- data/lib/net/ldap/entry.rb +208 -0
- data/lib/net/ldap/filter.rb +781 -0
- data/lib/net/ldap/password.rb +52 -0
- data/lib/net/ldap/pdu.rb +279 -0
- data/lib/net/ldif.rb +34 -0
- data/lib/net/snmp.rb +295 -0
- data/spec/integration/ssl_ber_spec.rb +33 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/ber/ber_spec.rb +109 -0
- data/spec/unit/ber/core_ext/string_spec.rb +51 -0
- data/spec/unit/ldap/entry_spec.rb +51 -0
- data/spec/unit/ldap/filter_spec.rb +83 -0
- data/spec/unit/ldap_spec.rb +48 -0
- data/test/common.rb +3 -0
- data/test/test_entry.rb +59 -0
- data/test/test_filter.rb +115 -0
- data/test/test_ldif.rb +68 -0
- data/test/test_password.rb +17 -0
- data/test/test_rename.rb +79 -0
- data/test/test_snmp.rb +114 -0
- data/test/testdata.ldif +101 -0
- data/testserver/ldapserver.rb +210 -0
- data/testserver/testdata.ldif +101 -0
- metadata +178 -0
@@ -0,0 +1,33 @@
|
|
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
|
+
flexmock(OpenSSL::SSL::SSLSocket).
|
20
|
+
new_instances.should_receive(:connect => nil)
|
21
|
+
|
22
|
+
@to = Net::LDAP::Connection.wrap_with_ssl(to)
|
23
|
+
@from = Net::LDAP::Connection.wrap_with_ssl(from)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should transmit strings" do
|
27
|
+
transmit('foo').should == 'foo'
|
28
|
+
end
|
29
|
+
it "should correctly transmit numbers" do
|
30
|
+
to.write 1234.to_ber
|
31
|
+
from.read_ber.should == 1234
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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,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,83 @@
|
|
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
|
+
].each do |filter_str|
|
29
|
+
context "from_rfc2254(#{filter_str.inspect})" do
|
30
|
+
attr_reader :filter
|
31
|
+
before(:each) do
|
32
|
+
@filter = Net::LDAP::Filter.from_rfc2254(filter_str)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should decode into a Net::LDAP::Filter" do
|
36
|
+
filter.should be_an_instance_of(Net::LDAP::Filter)
|
37
|
+
end
|
38
|
+
it "should survive roundtrip conversion to/from ber" do
|
39
|
+
ber = filter.to_ber
|
40
|
+
Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
|
41
|
+
filter
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
describe "<- .construct" do
|
48
|
+
it "should accept apostrophes in filters (regression)" do
|
49
|
+
Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "convenience filter constructors" do
|
54
|
+
def eq(attribute, value)
|
55
|
+
described_class.eq(attribute, value)
|
56
|
+
end
|
57
|
+
describe "<- .equals(attr, val)" do
|
58
|
+
it "should delegate to .eq with escaping" do
|
59
|
+
described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
describe "<- .begins(attr, val)" do
|
63
|
+
it "should delegate to .eq with escaping" do
|
64
|
+
described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
describe "<- .ends(attr, val)" do
|
68
|
+
it "should delegate to .eq with escaping" do
|
69
|
+
described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
describe "<- .contains(attr, val)" do
|
73
|
+
it "should delegate to .eq with escaping" do
|
74
|
+
described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
describe "<- .escape(str)" do
|
79
|
+
it "should escape !, &, *, :, | and ~" do
|
80
|
+
Net::LDAP::Filter.escape('!&*:|~').should == "\\21\\26\\2A\\3A\\7C\\7E"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Net::LDAP::Connection do
|
4
|
+
describe "initialize" do
|
5
|
+
context "when host is not responding" do
|
6
|
+
before(:each) do
|
7
|
+
flexmock(TCPSocket).
|
8
|
+
should_receive(:new).and_raise(Errno::ECONNREFUSED)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise LdapError" do
|
12
|
+
lambda {
|
13
|
+
Net::LDAP::Connection.new(
|
14
|
+
:server => 'test.mocked.com',
|
15
|
+
:port => 636)
|
16
|
+
}.should raise_error(Net::LDAP::LdapError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
context "when host is blocking the port" do
|
20
|
+
before(:each) do
|
21
|
+
flexmock(TCPSocket).
|
22
|
+
should_receive(:new).and_raise(SocketError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should raise LdapError" do
|
26
|
+
lambda {
|
27
|
+
Net::LDAP::Connection.new(
|
28
|
+
:server => 'test.mocked.com',
|
29
|
+
:port => 636)
|
30
|
+
}.should raise_error(Net::LDAP::LdapError)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context "on other exceptions" do
|
34
|
+
before(:each) do
|
35
|
+
flexmock(TCPSocket).
|
36
|
+
should_receive(:new).and_raise(NameError)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should rethrow the exception" do
|
40
|
+
lambda {
|
41
|
+
Net::LDAP::Connection.new(
|
42
|
+
:server => 'test.mocked.com',
|
43
|
+
:port => 636)
|
44
|
+
}.should raise_error(NameError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/test/common.rb
ADDED
data/test/test_entry.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'common'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
class TestEntry < Test::Unit::TestCase
|
5
|
+
Commented out until I can make it a spec.
|
6
|
+
context "An instance of Entry" do
|
7
|
+
setup do
|
8
|
+
@entry = Net::LDAP::Entry.new 'cn=Barbara,o=corp'
|
9
|
+
end
|
10
|
+
|
11
|
+
should "be initialized with the DN" do
|
12
|
+
assert_equal 'cn=Barbara,o=corp', @entry.dn
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'return an empty array when accessing a nonexistent attribute (index lookup)' do
|
16
|
+
assert_equal [], @entry['sn']
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'return an empty array when accessing a nonexistent attribute (method call)' do
|
20
|
+
assert_equal [], @entry.sn
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'create an attribute on assignment (index lookup)' do
|
24
|
+
@entry['sn'] = 'Jensen'
|
25
|
+
assert_equal ['Jensen'], @entry['sn']
|
26
|
+
end
|
27
|
+
|
28
|
+
should 'create an attribute on assignment (method call)' do
|
29
|
+
@entry.sn = 'Jensen'
|
30
|
+
assert_equal ['Jensen'], @entry.sn
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'have attributes accessible by index lookup' do
|
34
|
+
@entry['sn'] = 'Jensen'
|
35
|
+
assert_equal ['Jensen'], @entry['sn']
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'have attributes accessible using a Symbol as the index' do
|
39
|
+
@entry[:sn] = 'Jensen'
|
40
|
+
assert_equal ['Jensen'], @entry[:sn]
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'have attributes accessible by method call' do
|
44
|
+
@entry['sn'] = 'Jensen'
|
45
|
+
assert_equal ['Jensen'], @entry.sn
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'ignore case of attribute names' do
|
49
|
+
@entry['sn'] = 'Jensen'
|
50
|
+
assert_equal ['Jensen'], @entry.sn
|
51
|
+
assert_equal ['Jensen'], @entry.Sn
|
52
|
+
assert_equal ['Jensen'], @entry.SN
|
53
|
+
assert_equal ['Jensen'], @entry['sn']
|
54
|
+
assert_equal ['Jensen'], @entry['Sn']
|
55
|
+
assert_equal ['Jensen'], @entry['SN']
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
=end
|