net-ldap 0.0.5 → 0.1.0
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.
Potentially problematic release.
This version of net-ldap might be problematic. Click here for more details.
- data/History.txt +7 -6
- data/LICENSE +3 -2
- data/Manifest.txt +13 -5
- data/README.txt +34 -28
- data/Rakefile +115 -11
- data/lib/net-ldap.rb +1 -0
- data/lib/net/ber.rb +52 -514
- data/lib/net/ber/ber_parser.rb +112 -0
- data/lib/net/ldap.rb +486 -540
- data/lib/net/ldap/core_ext/all.rb +43 -0
- data/lib/net/ldap/core_ext/array.rb +42 -0
- data/lib/net/ldap/core_ext/bignum.rb +25 -0
- data/lib/net/ldap/core_ext/false_class.rb +11 -0
- data/lib/net/ldap/core_ext/fixnum.rb +64 -0
- data/lib/net/ldap/core_ext/string.rb +40 -0
- data/lib/net/ldap/core_ext/true_class.rb +11 -0
- data/lib/net/ldap/dataset.rb +64 -73
- data/lib/net/ldap/entry.rb +0 -9
- data/lib/net/ldap/filter.rb +1 -8
- data/lib/net/ldap/pdu.rb +2 -3
- data/lib/net/ldap/psw.rb +31 -38
- data/lib/net/ldif.rb +2 -7
- data/lib/net/snmp.rb +2 -4
- data/spec/integration/ssl_ber_spec.rb +36 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/ber/ber_spec.rb +18 -0
- data/test/common.rb +0 -4
- data/test/test_ber.rb +73 -95
- data/test/test_filter.rb +1 -1
- data/test/test_ldif.rb +1 -1
- data/test/test_snmp.rb +61 -78
- data/testserver/ldapserver.rb +0 -19
- metadata +118 -24
- data/Release-Announcement +0 -95
- data/pre-setup.rb +0 -45
- data/setup.rb +0 -1366
- data/tests/NOTICE.txt +0 -6
- data/tests/testldap.rb +0 -190
data/lib/net/ldap/pdu.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# $Id$
|
2
1
|
#
|
3
2
|
# LDAP PDU support classes
|
4
3
|
#
|
@@ -24,12 +23,12 @@
|
|
24
23
|
#
|
25
24
|
#---------------------------------------------------------------------------
|
26
25
|
|
27
|
-
|
26
|
+
require 'ostruct'
|
28
27
|
|
28
|
+
module Net
|
29
29
|
class LdapPduError < StandardError; end
|
30
30
|
|
31
31
|
class LdapPdu
|
32
|
-
|
33
32
|
BindRequest = 0
|
34
33
|
BindResult = 1
|
35
34
|
UnbindRequest = 2
|
data/lib/net/ldap/psw.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
# $Id$
|
2
|
-
#
|
3
|
-
#
|
4
1
|
#----------------------------------------------------------------------------
|
5
2
|
#
|
6
3
|
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
@@ -22,43 +19,39 @@
|
|
22
19
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
23
20
|
#
|
24
21
|
#---------------------------------------------------------------------------
|
25
|
-
#
|
26
|
-
#
|
27
22
|
|
23
|
+
require 'digest/sha1'
|
24
|
+
require 'digest/md5'
|
28
25
|
|
29
26
|
module Net
|
30
|
-
class LDAP
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
27
|
+
class LDAP
|
28
|
+
class Password
|
29
|
+
class << self
|
30
|
+
# Generate a password-hash suitable for inclusion in an LDAP
|
31
|
+
# attribute. Pass a hash type (currently supported: :md5 and :sha)
|
32
|
+
# and a plaintext password. This function will return a hashed
|
33
|
+
# representation.
|
34
|
+
#
|
35
|
+
# STUB: This is here to fulfill the requirements of an RFC, which
|
36
|
+
# one?
|
37
|
+
#
|
38
|
+
# TODO, gotta do salted-sha and (maybe) salted-md5.
|
39
|
+
# Should we provide sha1 as a synonym for sha1? I vote no because
|
40
|
+
# then should you also provide ssha1 for symmetry?
|
41
|
+
def generate(type, str)
|
42
|
+
digest, digest_name = case type
|
43
|
+
when :md5
|
44
|
+
[Digest::MD5.new, 'MD5']
|
45
|
+
when :sha
|
46
|
+
[Digest::SHA1.new, 'SHA']
|
47
|
+
else
|
48
|
+
raise Net::LDAP::LdapError.new("unsupported password-hash type (#{type})")
|
49
|
+
end
|
50
|
+
|
51
|
+
digest << str.to_s
|
52
|
+
return "{#{digest_name}}#{[digest.digest].pack('m').chomp }"
|
53
|
+
end
|
54
|
+
end
|
54
55
|
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
56
|
+
end
|
58
57
|
end
|
59
|
-
|
60
|
-
|
61
|
-
end # class LDAP
|
62
|
-
end # module Net
|
63
|
-
|
64
|
-
|
data/lib/net/ldif.rb
CHANGED
data/lib/net/snmp.rb
CHANGED
@@ -26,14 +26,12 @@
|
|
26
26
|
#
|
27
27
|
#
|
28
28
|
|
29
|
-
require 'net/ber'
|
30
|
-
|
31
|
-
|
32
29
|
module Net
|
33
30
|
|
34
31
|
class SNMP
|
32
|
+
VERSION = '0.1.0'
|
35
33
|
|
36
|
-
AsnSyntax = BER.compile_syntax({
|
34
|
+
AsnSyntax = Net::BER.compile_syntax({
|
37
35
|
:application => {
|
38
36
|
:primitive => {
|
39
37
|
1 => :integer, # Counter32, (RFC2578 sec 2)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'openssl'
|
5
|
+
|
6
|
+
require 'net/ldap'
|
7
|
+
|
8
|
+
describe "BER serialisation (SSL)" do
|
9
|
+
# Transmits str to #to and reads it back from #from.
|
10
|
+
#
|
11
|
+
def transmit(str)
|
12
|
+
to.write(str)
|
13
|
+
to.close
|
14
|
+
|
15
|
+
from.read
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :to, :from
|
19
|
+
before(:each) do
|
20
|
+
@from, @to = IO.pipe
|
21
|
+
|
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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'net/ber'
|
4
|
+
require 'net/ldap'
|
5
|
+
|
6
|
+
describe "Ber encoding of various types" do
|
7
|
+
def properly_encode_and_decode
|
8
|
+
simple_matcher('properly encode and decode') do |given|
|
9
|
+
given.to_ber.read_ber.should == given
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "array" do
|
14
|
+
it "should properly encode []" do
|
15
|
+
[].should properly_encode_and_decode
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/common.rb
CHANGED
data/test/test_ber.rb
CHANGED
@@ -1,100 +1,78 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# encoding: ASCII-8BIT
|
3
2
|
require 'common'
|
4
3
|
|
5
4
|
class TestBer < Test::Unit::TestCase
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax ))
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_ber_parser_on_ldap_bind_request
|
83
|
-
require 'stringio'
|
84
|
-
|
85
|
-
s = StringIO.new(
|
86
|
-
"0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" )
|
87
|
-
|
88
|
-
assert_equal(
|
89
|
-
[1, [3, "Administrator", "ad_is_bogus"]],
|
90
|
-
s.read_ber( Net::LDAP::AsnSyntax ))
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_oid
|
94
|
-
oid = Net::BER::BerIdentifiedOid.new( [1,3,6,1,2,1,1,1,0] )
|
95
|
-
assert_equal( "\006\b+\006\001\002\001\001\001\000", oid.to_ber )
|
96
|
-
|
97
|
-
oid = Net::BER::BerIdentifiedOid.new( "1.3.6.1.2.1.1.1.0" )
|
98
|
-
assert_equal( "\006\b+\006\001\002\001\001\001\000", oid.to_ber )
|
99
|
-
end
|
6
|
+
def test_encode_boolean
|
7
|
+
assert_equal( "\x01\x01\x01", true.to_ber ) # should actually be: 01 01 ff
|
8
|
+
assert_equal( "\x01\x01\x00", false.to_ber )
|
9
|
+
end
|
10
|
+
|
11
|
+
#def test_encode_nil
|
12
|
+
# assert_equal( "\x05\x00", nil.to_ber )
|
13
|
+
#end
|
14
|
+
|
15
|
+
def test_encode_integer
|
16
|
+
|
17
|
+
# Fixnum
|
18
|
+
#
|
19
|
+
#assert_equal( "\x02\x02\x96\x46", -27_066.to_ber )
|
20
|
+
#assert_equal( "\x02\x02\xFF\x7F", -129.to_ber )
|
21
|
+
#assert_equal( "\x02\x01\x80", -128.to_ber )
|
22
|
+
#assert_equal( "\x02\x01\xFF", -1.to_ber )
|
23
|
+
|
24
|
+
assert_equal( "\x02\x01\x00", 0.to_ber )
|
25
|
+
assert_equal( "\x02\x01\x01", 1.to_ber )
|
26
|
+
assert_equal( "\x02\x01\x7F", 127.to_ber )
|
27
|
+
assert_equal( "\x02\x01\x80", 128.to_ber )
|
28
|
+
assert_equal( "\x02\x01\xFF", 255.to_ber )
|
29
|
+
|
30
|
+
assert_equal( "\x02\x02\x01\x00", 256.to_ber )
|
31
|
+
assert_equal( "\x02\x02\xFF\xFF", 65535.to_ber )
|
32
|
+
|
33
|
+
assert_equal( "\x02\x03\x01\x00\x00", 65536.to_ber )
|
34
|
+
assert_equal( "\x02\x03\xFF\xFF\xFF", 16_777_215.to_ber )
|
35
|
+
|
36
|
+
assert_equal( "\x02\x04\x01\x00\x00\x00", 0x01000000.to_ber )
|
37
|
+
assert_equal( "\x02\x04\x3F\xFF\xFF\xFF", 0x3FFFFFFF.to_ber )
|
38
|
+
|
39
|
+
# Bignum
|
40
|
+
#
|
41
|
+
assert_equal( "\x02\x04\x4F\xFF\xFF\xFF", 0x4FFFFFFF.to_ber )
|
42
|
+
#assert_equal( "\x02\x05\x00\xFF\xFF\xFF\xFF", 0xFFFFFFFF.to_ber )
|
43
|
+
end
|
44
|
+
|
45
|
+
# TOD Add some much bigger numbers
|
46
|
+
# 5000000000 is a Bignum, which hits different code.
|
47
|
+
def test_ber_integers
|
48
|
+
assert_equal( "\002\001\005", 5.to_ber )
|
49
|
+
assert_equal( "\002\002\001\364", 500.to_ber )
|
50
|
+
assert_equal( "\x02\x02\xC3P", 50000.to_ber )
|
51
|
+
assert_equal( "\002\005\001*\005\362\000", 5000000000.to_ber )
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_ber_bignums
|
55
|
+
# Some of these values are Fixnums and some are Bignums. Different BER code.
|
56
|
+
100.times do |p|
|
57
|
+
n = 2 << p
|
58
|
+
assert_equal(n, n.to_ber.read_ber, "2**#{p} could not be read back")
|
59
|
+
|
60
|
+
n = 5 * 10**p
|
61
|
+
assert_equal(n, n.to_ber.read_ber)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_ber_parsing
|
66
|
+
assert_equal( 6, "\002\001\006".read_ber( Net::LDAP::AsnSyntax ))
|
67
|
+
assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax ))
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_ber_parser_on_ldap_bind_request
|
71
|
+
s = StringIO.new(
|
72
|
+
"0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" )
|
73
|
+
|
74
|
+
assert_equal(
|
75
|
+
[1, [3, "Administrator", "ad_is_bogus"]],
|
76
|
+
s.read_ber( Net::LDAP::AsnSyntax ))
|
77
|
+
end
|
100
78
|
end
|
data/test/test_filter.rb
CHANGED
@@ -74,7 +74,7 @@ class TestFilter < Test::Unit::TestCase
|
|
74
74
|
Net::LDAP::Filter.construct("objectclass=aaa*bbb*"),
|
75
75
|
Net::LDAP::Filter.construct("objectclass=aaa*bbb*ccc*"),
|
76
76
|
].each {|ber|
|
77
|
-
|
77
|
+
f = Net::LDAP::Filter.parse_ber( ber.to_ber.read_ber( Net::LDAP::AsnSyntax) )
|
78
78
|
assert( f == ber )
|
79
79
|
assert_equal( f.to_ber, ber.to_ber )
|
80
80
|
}
|
data/test/test_ldif.rb
CHANGED
@@ -11,7 +11,7 @@ class TestLdif < Test::Unit::TestCase
|
|
11
11
|
TestLdifFilename = "#{File.dirname(__FILE__)}/testdata.ldif"
|
12
12
|
|
13
13
|
def test_empty_ldif
|
14
|
-
ds = Net::LDAP::Dataset
|
14
|
+
ds = Net::LDAP::Dataset.read_ldif( StringIO.new )
|
15
15
|
assert_equal( true, ds.empty? )
|
16
16
|
end
|
17
17
|
|
data/test/test_snmp.rb
CHANGED
@@ -18,111 +18,94 @@ class TestSnmp < Test::Unit::TestCase
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_invalid_packet
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
data = "xxxx"
|
22
|
+
assert_raise( Net::BER::BerError ) {
|
23
|
+
ary = data.read_ber(Net::SNMP::AsnSyntax)
|
24
|
+
}
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
|
-
# The method String#read_ber! added by Net::BER consumes a well-formed BER object
|
29
|
-
# from the head of a string. If it doesn't find a complete, well-formed BER object,
|
30
|
-
# it returns nil and leaves the string unchanged. If it finds an object, it returns
|
31
|
-
# the object and removes it from the head of the string. This is good for handling
|
32
|
-
# partially-received data streams, such as from network connections.
|
33
|
-
def test_consume_string
|
34
|
-
data = "xxx"
|
35
|
-
assert_equal( nil, data.read_ber! )
|
36
|
-
assert_equal( "xxx", data )
|
37
|
-
|
38
|
-
data = SnmpGetRequest + "!!!"
|
39
|
-
ary = data.read_ber!( Net::SNMP::AsnSyntax )
|
40
|
-
assert_equal( "!!!", data )
|
41
|
-
assert ary.is_a?(Array)
|
42
|
-
assert ary.is_a?(Net::BER::BerIdentifiedArray)
|
43
|
-
end
|
44
|
-
|
45
28
|
def test_weird_packet
|
46
|
-
|
47
|
-
|
48
|
-
|
29
|
+
assert_raise( Net::SnmpPdu::Error ) {
|
30
|
+
Net::SnmpPdu.parse("aaaaaaaaaaaaaa")
|
31
|
+
}
|
49
32
|
end
|
50
33
|
|
51
34
|
def test_get_request
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
35
|
+
data = SnmpGetRequest.dup
|
36
|
+
pkt = data.read_ber(Net::SNMP::AsnSyntax)
|
37
|
+
assert pkt.is_a?(Net::BER::BerIdentifiedArray)
|
38
|
+
assert_equal( 48, pkt.ber_identifier) # Constructed [0], signifies GetRequest
|
56
39
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
40
|
+
pdu = Net::SnmpPdu.parse(pkt)
|
41
|
+
assert_equal(:get_request, pdu.pdu_type )
|
42
|
+
assert_equal(16170, pdu.request_id ) # whatever was in the test data. 16170 is not magic.
|
43
|
+
assert_equal( [[[1,3,6,1,2,1,1,1,0],nil]], pdu.variables )
|
61
44
|
|
62
|
-
|
45
|
+
assert_equal( pdu.to_ber_string, SnmpGetRequest )
|
63
46
|
end
|
64
47
|
|
65
48
|
def test_empty_pdu
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
49
|
+
pdu = Net::SnmpPdu.new
|
50
|
+
assert_raise( Net::SnmpPdu::Error ) {
|
51
|
+
pdu.to_ber_string
|
52
|
+
}
|
70
53
|
end
|
71
54
|
|
72
55
|
def test_malformations
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
56
|
+
pdu = Net::SnmpPdu.new
|
57
|
+
pdu.version = 0
|
58
|
+
pdu.version = 2
|
59
|
+
assert_raise( Net::SnmpPdu::Error ) {
|
60
|
+
pdu.version = 100
|
61
|
+
}
|
62
|
+
|
63
|
+
pdu.pdu_type = :get_request
|
64
|
+
pdu.pdu_type = :get_next_request
|
65
|
+
pdu.pdu_type = :get_response
|
66
|
+
pdu.pdu_type = :set_request
|
67
|
+
pdu.pdu_type = :trap
|
68
|
+
assert_raise( Net::SnmpPdu::Error ) {
|
69
|
+
pdu.pdu_type = :something_else
|
70
|
+
}
|
88
71
|
end
|
89
72
|
|
90
73
|
def test_make_response
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
74
|
+
pdu = Net::SnmpPdu.new
|
75
|
+
pdu.version = 0
|
76
|
+
pdu.community = "public"
|
77
|
+
pdu.pdu_type = :get_response
|
78
|
+
pdu.request_id = 9999
|
79
|
+
pdu.error_status = 0
|
80
|
+
pdu.error_index = 0
|
81
|
+
pdu.add_variable_binding [1,3,6,1,2,1,1,1,0], "test"
|
82
|
+
|
83
|
+
assert_equal( SnmpGetResponse, pdu.to_ber_string )
|
101
84
|
end
|
102
85
|
|
103
86
|
def test_make_bad_response
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
87
|
+
pdu = Net::SnmpPdu.new
|
88
|
+
assert_raise(Net::SnmpPdu::Error) {pdu.to_ber_string}
|
89
|
+
pdu.pdu_type = :get_response
|
90
|
+
pdu.request_id = 999
|
91
|
+
pdu.to_ber_string
|
92
|
+
# Not specifying variables doesn't create an error. (Maybe it should?)
|
110
93
|
end
|
111
94
|
|
112
95
|
def test_snmp_integers
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
96
|
+
c32 = Net::SNMP::Counter32.new(100)
|
97
|
+
assert_equal( "A\001d", c32.to_ber )
|
98
|
+
g32 = Net::SNMP::Gauge32.new(100)
|
99
|
+
assert_equal( "B\001d", g32.to_ber )
|
100
|
+
t32 = Net::SNMP::TimeTicks32.new(100)
|
101
|
+
assert_equal( "C\001d", t32.to_ber )
|
119
102
|
end
|
120
103
|
|
121
104
|
def test_community
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
105
|
+
data = SnmpGetRequestXXX.dup
|
106
|
+
ary = data.read_ber(Net::SNMP::AsnSyntax)
|
107
|
+
pdu = Net::SnmpPdu.parse( ary )
|
108
|
+
assert_equal( "xxxxxx", pdu.community )
|
126
109
|
end
|
127
110
|
|
128
111
|
end
|