ruby-net-ldap 0.0.1
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/COPYING +272 -0
- data/ChangeLog +28 -0
- data/LICENCE +55 -0
- data/README +29 -0
- data/lib/net/ber.rb +278 -0
- data/lib/net/ldap.rb +1041 -0
- data/lib/net/ldap/dataset.rb +108 -0
- data/lib/net/ldap/entry.rb +82 -0
- data/lib/net/ldap/filter.rb +279 -0
- data/lib/net/ldap/pdu.rb +155 -0
- data/lib/net/ldap/psw.rb +64 -0
- data/lib/net/ldif.rb +39 -0
- data/tests/testber.rb +42 -0
- data/tests/testdata.ldif +101 -0
- data/tests/testem.rb +11 -0
- data/tests/testldap.rb +190 -0
- data/tests/testldif.rb +69 -0
- data/tests/testpsw.rb +28 -0
- metadata +71 -0
data/lib/net/ldap/pdu.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# $Id: pdu.rb 85 2006-04-30 16:31:08Z blackhedd $
|
2
|
+
#
|
3
|
+
# LDAP PDU support classes
|
4
|
+
#
|
5
|
+
#
|
6
|
+
#----------------------------------------------------------------------------
|
7
|
+
#
|
8
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
#
|
10
|
+
# Gmail: garbagecat10
|
11
|
+
#
|
12
|
+
# This program is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# This program is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU General Public License
|
23
|
+
# along with this program; if not, write to the Free Software
|
24
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
+
#
|
26
|
+
#---------------------------------------------------------------------------
|
27
|
+
#
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
module Net
|
32
|
+
|
33
|
+
|
34
|
+
class LdapPduError < Exception; end
|
35
|
+
|
36
|
+
|
37
|
+
class LdapPdu
|
38
|
+
|
39
|
+
BindResult = 1
|
40
|
+
SearchReturnedData = 4
|
41
|
+
SearchResult = 5
|
42
|
+
ModifyResponse = 7
|
43
|
+
AddResponse = 9
|
44
|
+
DeleteResponse = 11
|
45
|
+
ModifyRDNResponse = 13
|
46
|
+
|
47
|
+
attr_reader :msg_id, :app_tag
|
48
|
+
attr_reader :search_dn, :search_attributes, :search_entry
|
49
|
+
|
50
|
+
#
|
51
|
+
# initialize
|
52
|
+
# An LDAP PDU always looks like a BerSequence with
|
53
|
+
# two elements: an integer (message-id number), and
|
54
|
+
# an application-specific sequence.
|
55
|
+
# The application-specific tag in the sequence tells
|
56
|
+
# us what kind of packet it is, and each kind has its
|
57
|
+
# own format, defined in RFC-1777.
|
58
|
+
# Observe that many clients (such as ldapsearch)
|
59
|
+
# do not necessarily enforce the expected application
|
60
|
+
# tags on received protocol packets. This implementation
|
61
|
+
# does interpret the RFC strictly in this regard, and
|
62
|
+
# it remains to be seen whether there are servers out
|
63
|
+
# there that will not work well with our approach.
|
64
|
+
#
|
65
|
+
def initialize ber_object
|
66
|
+
begin
|
67
|
+
@msg_id = ber_object[0].to_i
|
68
|
+
@app_tag = ber_object[1].ber_identifier - 0x60
|
69
|
+
rescue
|
70
|
+
# any error becomes a data-format error
|
71
|
+
raise LdapPduError.new( "ldap-pdu format error" )
|
72
|
+
end
|
73
|
+
|
74
|
+
case @app_tag
|
75
|
+
when BindResult
|
76
|
+
parse_ldap_result ber_object[1]
|
77
|
+
when SearchReturnedData
|
78
|
+
parse_search_return ber_object[1]
|
79
|
+
when SearchResult
|
80
|
+
parse_ldap_result ber_object[1]
|
81
|
+
when ModifyResponse
|
82
|
+
parse_ldap_result ber_object[1]
|
83
|
+
when AddResponse
|
84
|
+
parse_ldap_result ber_object[1]
|
85
|
+
when DeleteResponse
|
86
|
+
parse_ldap_result ber_object[1]
|
87
|
+
when ModifyRDNResponse
|
88
|
+
parse_ldap_result ber_object[1]
|
89
|
+
else
|
90
|
+
raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# result_code
|
96
|
+
# This returns an LDAP result code taken from the PDU,
|
97
|
+
# but it will be nil if there wasn't a result code.
|
98
|
+
# That can easily happen depending on the type of packet.
|
99
|
+
#
|
100
|
+
def result_code code = :resultCode
|
101
|
+
@ldap_result and @ldap_result[code]
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
#
|
108
|
+
# parse_ldap_result
|
109
|
+
#
|
110
|
+
def parse_ldap_result sequence
|
111
|
+
sequence.length >= 3 or raise LdapPduError
|
112
|
+
@ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# parse_search_return
|
117
|
+
# Definition from RFC 1777 (we're handling application-4 here)
|
118
|
+
#
|
119
|
+
# Search Response ::=
|
120
|
+
# CHOICE {
|
121
|
+
# entry [APPLICATION 4] SEQUENCE {
|
122
|
+
# objectName LDAPDN,
|
123
|
+
# attributes SEQUENCE OF SEQUENCE {
|
124
|
+
# AttributeType,
|
125
|
+
# SET OF AttributeValue
|
126
|
+
# }
|
127
|
+
# },
|
128
|
+
# resultCode [APPLICATION 5] LDAPResult
|
129
|
+
# }
|
130
|
+
#
|
131
|
+
# We concoct a search response that is a hash of the returned attribute values.
|
132
|
+
# NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
|
133
|
+
# This is to make them more predictable for user programs, but it
|
134
|
+
# may not be a good idea. Maybe this should be configurable.
|
135
|
+
# ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes,
|
136
|
+
# we also return @search_entry, which is an LDAP::Entry object.
|
137
|
+
# If that works out well, then we'll remove the first two.
|
138
|
+
#
|
139
|
+
def parse_search_return sequence
|
140
|
+
sequence.length >= 2 or raise LdapPduError
|
141
|
+
@search_entry = LDAP::Entry.new( sequence[0] )
|
142
|
+
@search_dn = sequence[0]
|
143
|
+
@search_attributes = {}
|
144
|
+
sequence[1].each {|seq|
|
145
|
+
@search_entry[seq[0]] = seq[1]
|
146
|
+
@search_attributes[seq[0].downcase.intern] = seq[1]
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end # module Net
|
155
|
+
|
data/lib/net/ldap/psw.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# $Id: psw.rb 73 2006-04-24 21:59:35Z blackhedd $
|
2
|
+
#
|
3
|
+
#
|
4
|
+
#----------------------------------------------------------------------------
|
5
|
+
#
|
6
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
7
|
+
#
|
8
|
+
# Gmail: garbagecat10
|
9
|
+
#
|
10
|
+
# This program is free software; you can redistribute it and/or modify
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
12
|
+
# the Free Software Foundation; either version 2 of the License, or
|
13
|
+
# (at your option) any later version.
|
14
|
+
#
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
# GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License
|
21
|
+
# along with this program; if not, write to the Free Software
|
22
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
23
|
+
#
|
24
|
+
#---------------------------------------------------------------------------
|
25
|
+
#
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
module Net
|
30
|
+
class LDAP
|
31
|
+
|
32
|
+
|
33
|
+
class Password
|
34
|
+
class << self
|
35
|
+
|
36
|
+
# Generate a password-hash suitable for inclusion in an LDAP attribute.
|
37
|
+
# Pass a hash type (currently supported: :md5 and :sha) and a plaintext
|
38
|
+
# password. This function will return a hashed representation.
|
39
|
+
# STUB: This is here to fulfill the requirements of an RFC, which one?
|
40
|
+
# TODO, gotta do salted-sha and (maybe) salted-md5.
|
41
|
+
# Should we provide sha1 as a synonym for sha1? I vote no because then
|
42
|
+
# should you also provide ssha1 for symmetry?
|
43
|
+
def generate( type, str )
|
44
|
+
case type
|
45
|
+
when :md5
|
46
|
+
require 'md5'
|
47
|
+
"{MD5}#{ [MD5.new( str.to_s ).digest].pack("m").chomp }"
|
48
|
+
when :sha
|
49
|
+
require 'sha1'
|
50
|
+
"{SHA}#{ [SHA1.new( str.to_s ).digest].pack("m").chomp }"
|
51
|
+
# when ssha
|
52
|
+
else
|
53
|
+
raise Net::LDAP::LdapError.new( "unsupported password-hash type (#{type})" )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end # class LDAP
|
62
|
+
end # module Net
|
63
|
+
|
64
|
+
|
data/lib/net/ldif.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# $Id: ldif.rb 78 2006-04-26 02:57:34Z blackhedd $
|
2
|
+
#
|
3
|
+
# Net::LDIF for Ruby
|
4
|
+
#
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
8
|
+
#
|
9
|
+
# Gmail: garbagecat10
|
10
|
+
#
|
11
|
+
# This program is free software; you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
13
|
+
# the Free Software Foundation; either version 2 of the License, or
|
14
|
+
# (at your option) any later version.
|
15
|
+
#
|
16
|
+
# This program is distributed in the hope that it will be useful,
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
# GNU General Public License for more details.
|
20
|
+
#
|
21
|
+
# You should have received a copy of the GNU General Public License
|
22
|
+
# along with this program; if not, write to the Free Software
|
23
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24
|
+
#
|
25
|
+
#
|
26
|
+
|
27
|
+
# THIS FILE IS A STUB.
|
28
|
+
|
29
|
+
module Net
|
30
|
+
|
31
|
+
class LDIF
|
32
|
+
|
33
|
+
|
34
|
+
end # class LDIF
|
35
|
+
|
36
|
+
|
37
|
+
end # module Net
|
38
|
+
|
39
|
+
|
data/tests/testber.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# $Id: testber.rb 57 2006-04-18 00:18:48Z blackhedd $
|
2
|
+
#
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
$:.unshift "lib"
|
7
|
+
|
8
|
+
require 'net/ldap'
|
9
|
+
require 'stringio'
|
10
|
+
|
11
|
+
|
12
|
+
class TestBer < Test::Unit::TestCase
|
13
|
+
|
14
|
+
def setup
|
15
|
+
end
|
16
|
+
|
17
|
+
# TODO: Add some much bigger numbers
|
18
|
+
# 5000000000 is a Bignum, which hits different code.
|
19
|
+
def test_ber_integers
|
20
|
+
assert_equal( "\002\001\005", 5.to_ber )
|
21
|
+
assert_equal( "\002\002\203t", 500.to_ber )
|
22
|
+
assert_equal( "\002\003\203\206P", 50000.to_ber )
|
23
|
+
assert_equal( "\002\005\222\320\227\344\000", 5000000000.to_ber )
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_ber_parsing
|
27
|
+
assert_equal( 6, "\002\001\006".read_ber( Net::LDAP::AsnSyntax ))
|
28
|
+
assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax ))
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def test_ber_parser_on_ldap_bind_request
|
33
|
+
s = StringIO.new "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus"
|
34
|
+
assert_equal( [1, [3, "Administrator", "ad_is_bogus"]], s.read_ber( Net::LDAP::AsnSyntax ))
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
data/tests/testdata.ldif
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# $Id: testdata.ldif 50 2006-04-17 17:57:33Z blackhedd $
|
2
|
+
#
|
3
|
+
# This is test-data for an LDAP server in LDIF format.
|
4
|
+
#
|
5
|
+
dn: dc=bayshorenetworks,dc=com
|
6
|
+
objectClass: dcObject
|
7
|
+
objectClass: organization
|
8
|
+
o: Bayshore Networks LLC
|
9
|
+
dc: bayshorenetworks
|
10
|
+
|
11
|
+
dn: cn=Manager,dc=bayshorenetworks,dc=com
|
12
|
+
objectClass: organizationalrole
|
13
|
+
cn: Manager
|
14
|
+
|
15
|
+
dn: ou=people,dc=bayshorenetworks,dc=com
|
16
|
+
objectClass: organizationalunit
|
17
|
+
ou: people
|
18
|
+
|
19
|
+
dn: ou=privileges,dc=bayshorenetworks,dc=com
|
20
|
+
objectClass: organizationalunit
|
21
|
+
ou: privileges
|
22
|
+
|
23
|
+
dn: ou=roles,dc=bayshorenetworks,dc=com
|
24
|
+
objectClass: organizationalunit
|
25
|
+
ou: roles
|
26
|
+
|
27
|
+
dn: ou=office,dc=bayshorenetworks,dc=com
|
28
|
+
objectClass: organizationalunit
|
29
|
+
ou: office
|
30
|
+
|
31
|
+
dn: mail=nogoodnik@steamheat.net,ou=people,dc=bayshorenetworks,dc=com
|
32
|
+
cn: Bob Fosse
|
33
|
+
mail: nogoodnik@steamheat.net
|
34
|
+
sn: Fosse
|
35
|
+
ou: people
|
36
|
+
objectClass: top
|
37
|
+
objectClass: inetorgperson
|
38
|
+
objectClass: authorizedperson
|
39
|
+
hasAccessRole: uniqueIdentifier=engineer,ou=roles
|
40
|
+
hasAccessRole: uniqueIdentifier=ldapadmin,ou=roles
|
41
|
+
hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles
|
42
|
+
hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles
|
43
|
+
hasAccessRole: uniqueIdentifier=ogilvy_eagle_user,ou=roles
|
44
|
+
hasAccessRole: uniqueIdentifier=greenplug_user,ou=roles
|
45
|
+
hasAccessRole: uniqueIdentifier=brandplace_logging_user,ou=roles
|
46
|
+
hasAccessRole: uniqueIdentifier=brandplace_report_user,ou=roles
|
47
|
+
hasAccessRole: uniqueIdentifier=workorder_user,ou=roles
|
48
|
+
hasAccessRole: uniqueIdentifier=bayshore_eagle_user,ou=roles
|
49
|
+
hasAccessRole: uniqueIdentifier=bayshore_eagle_superuser,ou=roles
|
50
|
+
hasAccessRole: uniqueIdentifier=kledaras_user,ou=roles
|
51
|
+
|
52
|
+
dn: mail=elephant@steamheat.net,ou=people,dc=bayshorenetworks,dc=com
|
53
|
+
cn: Gwen Verdon
|
54
|
+
mail: elephant@steamheat.net
|
55
|
+
sn: Verdon
|
56
|
+
ou: people
|
57
|
+
objectClass: top
|
58
|
+
objectClass: inetorgperson
|
59
|
+
objectClass: authorizedperson
|
60
|
+
hasAccessRole: uniqueIdentifier=brandplace_report_user,ou=roles
|
61
|
+
hasAccessRole: uniqueIdentifier=engineer,ou=roles
|
62
|
+
hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles
|
63
|
+
hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles
|
64
|
+
hasAccessRole: uniqueIdentifier=ldapadmin,ou=roles
|
65
|
+
|
66
|
+
dn: uniqueIdentifier=engineering,ou=privileges,dc=bayshorenetworks,dc=com
|
67
|
+
uniqueIdentifier: engineering
|
68
|
+
ou: privileges
|
69
|
+
objectClass: accessPrivilege
|
70
|
+
|
71
|
+
dn: uniqueIdentifier=engineer,ou=roles,dc=bayshorenetworks,dc=com
|
72
|
+
uniqueIdentifier: engineer
|
73
|
+
ou: roles
|
74
|
+
objectClass: accessRole
|
75
|
+
hasAccessPrivilege: uniqueIdentifier=engineering,ou=privileges
|
76
|
+
|
77
|
+
dn: uniqueIdentifier=ldapadmin,ou=roles,dc=bayshorenetworks,dc=com
|
78
|
+
uniqueIdentifier: ldapadmin
|
79
|
+
ou: roles
|
80
|
+
objectClass: accessRole
|
81
|
+
|
82
|
+
dn: uniqueIdentifier=ldapsuperadmin,ou=roles,dc=bayshorenetworks,dc=com
|
83
|
+
uniqueIdentifier: ldapsuperadmin
|
84
|
+
ou: roles
|
85
|
+
objectClass: accessRole
|
86
|
+
|
87
|
+
dn: mail=catperson@steamheat.net,ou=people,dc=bayshorenetworks,dc=com
|
88
|
+
cn: Sid Sorokin
|
89
|
+
mail: catperson@steamheat.net
|
90
|
+
sn: Sorokin
|
91
|
+
ou: people
|
92
|
+
objectClass: top
|
93
|
+
objectClass: inetorgperson
|
94
|
+
objectClass: authorizedperson
|
95
|
+
hasAccessRole: uniqueIdentifier=engineer,ou=roles
|
96
|
+
hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles
|
97
|
+
hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles
|
98
|
+
hasAccessRole: uniqueIdentifier=ogilvy_eagle_user,ou=roles
|
99
|
+
hasAccessRole: uniqueIdentifier=greenplug_user,ou=roles
|
100
|
+
hasAccessRole: uniqueIdentifier=workorder_user,ou=roles
|
101
|
+
|
data/tests/testem.rb
ADDED
data/tests/testldap.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# $Id: testldap.rb 65 2006-04-23 01:17:49Z blackhedd $
|
2
|
+
#
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
$:.unshift "lib"
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
require 'net/ldap'
|
11
|
+
require 'stringio'
|
12
|
+
|
13
|
+
|
14
|
+
class TestLdapClient < Test::Unit::TestCase
|
15
|
+
|
16
|
+
# TODO: these tests crash and burn if the associated
|
17
|
+
# LDAP testserver isn't up and running.
|
18
|
+
# We rely on being able to read a file with test data
|
19
|
+
# in LDIF format.
|
20
|
+
# TODO, WARNING: for the moment, this data is in a file
|
21
|
+
# whose name and location are HARDCODED into the
|
22
|
+
# instance method load_test_data.
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@host = "127.0.0.1"
|
26
|
+
@port = 3890
|
27
|
+
@auth = {
|
28
|
+
:method => :simple,
|
29
|
+
:username => "cn=bigshot,dc=bayshorenetworks,dc=com",
|
30
|
+
:password => "opensesame"
|
31
|
+
}
|
32
|
+
|
33
|
+
@ldif = load_test_data
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
# Get some test data which will be used to validate
|
39
|
+
# the responses from the test LDAP server we will
|
40
|
+
# connect to.
|
41
|
+
# TODO, Bogus: we are HARDCODING the location of the file for now.
|
42
|
+
#
|
43
|
+
def load_test_data
|
44
|
+
ary = File.readlines( "tests/testdata.ldif" )
|
45
|
+
hash = {}
|
46
|
+
while line = ary.shift and line.chomp!
|
47
|
+
if line =~ /^dn:[\s]*/i
|
48
|
+
dn = $'
|
49
|
+
hash[dn] = {}
|
50
|
+
while attr = ary.shift and attr.chomp! and attr =~ /^([\w]+)[\s]*:[\s]*/
|
51
|
+
hash[dn][$1.downcase.intern] ||= []
|
52
|
+
hash[dn][$1.downcase.intern] << $'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
# Binding tests.
|
62
|
+
# Need tests for all kinds of network failures and incorrect auth.
|
63
|
+
# TODO: Implement a class-level timeout for operations like bind.
|
64
|
+
# Search has a timeout defined at the protocol level, other ops do not.
|
65
|
+
# TODO, use constants for the LDAP result codes, rather than hardcoding them.
|
66
|
+
def test_bind
|
67
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth
|
68
|
+
assert_equal( true, ldap.bind )
|
69
|
+
assert_equal( 0, ldap.get_operation_result.code )
|
70
|
+
assert_equal( "Success", ldap.get_operation_result.message )
|
71
|
+
|
72
|
+
bad_username = @auth.merge( {:username => "cn=badguy,dc=imposters,dc=com"} )
|
73
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => bad_username
|
74
|
+
assert_equal( false, ldap.bind )
|
75
|
+
assert_equal( 48, ldap.get_operation_result.code )
|
76
|
+
assert_equal( "Inappropriate Authentication", ldap.get_operation_result.message )
|
77
|
+
|
78
|
+
bad_password = @auth.merge( {:password => "cornhusk"} )
|
79
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => bad_password
|
80
|
+
assert_equal( false, ldap.bind )
|
81
|
+
assert_equal( 49, ldap.get_operation_result.code )
|
82
|
+
assert_equal( "Invalid Credentials", ldap.get_operation_result.message )
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
def test_search
|
88
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth
|
89
|
+
|
90
|
+
search = {:base => "dc=smalldomain,dc=com"}
|
91
|
+
assert_equal( false, ldap.search( search ))
|
92
|
+
assert_equal( 32, ldap.get_operation_result.code )
|
93
|
+
|
94
|
+
search = {:base => "dc=bayshorenetworks,dc=com"}
|
95
|
+
assert_equal( true, ldap.search( search ))
|
96
|
+
assert_equal( 0, ldap.get_operation_result.code )
|
97
|
+
|
98
|
+
ldap.search( search ) {|res|
|
99
|
+
assert_equal( res, @ldif )
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
# This is a helper routine for test_search_attributes.
|
107
|
+
def internal_test_search_attributes attrs_to_search
|
108
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth
|
109
|
+
assert( ldap.bind )
|
110
|
+
|
111
|
+
search = {
|
112
|
+
:base => "dc=bayshorenetworks,dc=com",
|
113
|
+
:attributes => attrs_to_search
|
114
|
+
}
|
115
|
+
|
116
|
+
ldif = @ldif
|
117
|
+
ldif.each {|dn,entry|
|
118
|
+
entry.delete_if {|attr,value|
|
119
|
+
! attrs_to_search.include?(attr)
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
assert_equal( true, ldap.search( search ))
|
124
|
+
ldap.search( search ) {|res|
|
125
|
+
res_keys = res.keys.sort
|
126
|
+
ldif_keys = ldif.keys.sort
|
127
|
+
assert( res_keys, ldif_keys )
|
128
|
+
res.keys.each {|rk|
|
129
|
+
assert( res[rk], ldif[rk] )
|
130
|
+
}
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def test_search_attributes
|
136
|
+
internal_test_search_attributes [:mail]
|
137
|
+
internal_test_search_attributes [:cn]
|
138
|
+
internal_test_search_attributes [:ou]
|
139
|
+
internal_test_search_attributes [:hasaccessprivilege]
|
140
|
+
internal_test_search_attributes ["mail"]
|
141
|
+
internal_test_search_attributes ["cn"]
|
142
|
+
internal_test_search_attributes ["ou"]
|
143
|
+
internal_test_search_attributes ["hasaccessrole"]
|
144
|
+
|
145
|
+
internal_test_search_attributes [:mail, :cn, :ou, :hasaccessrole]
|
146
|
+
internal_test_search_attributes [:mail, "cn", :ou, "hasaccessrole"]
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def test_search_filters
|
151
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth
|
152
|
+
search = {
|
153
|
+
:base => "dc=bayshorenetworks,dc=com",
|
154
|
+
:filter => Net::LDAP::Filter.eq( "sn", "Fosse" )
|
155
|
+
}
|
156
|
+
|
157
|
+
ldap.search( search ) {|res|
|
158
|
+
p res
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
def test_open
|
165
|
+
ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth
|
166
|
+
ldap.open {|ldap|
|
167
|
+
10.times {
|
168
|
+
rc = ldap.search( :base => "dc=bayshorenetworks,dc=com" )
|
169
|
+
assert_equal( true, rc )
|
170
|
+
}
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
def test_ldap_open
|
176
|
+
Net::LDAP.open( :host => @host, :port => @port, :auth => @auth ) {|ldap|
|
177
|
+
10.times {
|
178
|
+
rc = ldap.search( :base => "dc=bayshorenetworks,dc=com" )
|
179
|
+
assert_equal( true, rc )
|
180
|
+
}
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
|