net-ldap 0.14.0 → 0.16.3

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.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +5 -2
  4. data/.rubocop_todo.yml +343 -219
  5. data/.travis.yml +27 -3
  6. data/CONTRIBUTING.md +1 -1
  7. data/History.rdoc +21 -0
  8. data/README.rdoc +10 -7
  9. data/Rakefile +1 -1
  10. data/lib/net-ldap.rb +1 -1
  11. data/lib/net/ber.rb +5 -6
  12. data/lib/net/ber/ber_parser.rb +3 -3
  13. data/lib/net/ber/core_ext.rb +6 -6
  14. data/lib/net/ldap.rb +65 -55
  15. data/lib/net/ldap/auth_adapter/gss_spnego.rb +2 -2
  16. data/lib/net/ldap/auth_adapter/sasl.rb +4 -2
  17. data/lib/net/ldap/auth_adapter/simple.rb +1 -1
  18. data/lib/net/ldap/connection.rb +58 -35
  19. data/lib/net/ldap/dataset.rb +2 -2
  20. data/lib/net/ldap/dn.rb +13 -14
  21. data/lib/net/ldap/entry.rb +5 -6
  22. data/lib/net/ldap/error.rb +1 -0
  23. data/lib/net/ldap/filter.rb +10 -3
  24. data/lib/net/ldap/instrumentation.rb +2 -2
  25. data/lib/net/ldap/password.rb +3 -5
  26. data/lib/net/ldap/pdu.rb +1 -1
  27. data/lib/net/ldap/version.rb +1 -1
  28. data/lib/net/snmp.rb +1 -1
  29. data/net-ldap.gemspec +4 -4
  30. data/script/ldap-docker +12 -0
  31. data/test/ber/test_ber.rb +1 -1
  32. data/test/fixtures/ca/docker-ca.pem +18 -0
  33. data/test/fixtures/{openldap/retcode.ldif → ldif/06-retcode.ldif} +7 -8
  34. data/test/fixtures/ldif/50-seed.ldif +374 -0
  35. data/test/integration/test_add.rb +1 -3
  36. data/test/integration/test_ber.rb +2 -2
  37. data/test/integration/test_bind.rb +193 -14
  38. data/test/integration/test_delete.rb +1 -3
  39. data/test/integration/test_open.rb +10 -11
  40. data/test/integration/test_password_modify.rb +29 -16
  41. data/test/integration/test_return_codes.rb +12 -4
  42. data/test/integration/test_search.rb +8 -8
  43. data/test/test_dn.rb +2 -3
  44. data/test/test_entry.rb +3 -2
  45. data/test/test_filter_parser.rb +5 -0
  46. data/test/test_helper.rb +12 -5
  47. data/test/test_ldap.rb +5 -5
  48. data/test/test_ldap_connection.rb +47 -35
  49. data/test/test_ldif.rb +13 -13
  50. data/test/test_password.rb +2 -2
  51. data/test/test_snmp.rb +4 -5
  52. data/test/test_ssl_ber.rb +7 -3
  53. data/testserver/ldapserver.rb +13 -22
  54. metadata +17 -26
  55. data/script/install-openldap +0 -115
  56. data/test/fixtures/cacert.pem +0 -20
  57. data/test/fixtures/openldap/memberof.ldif +0 -33
  58. data/test/fixtures/openldap/slapd.conf.ldif +0 -67
  59. data/test/fixtures/seed.ldif +0 -374
  60. data/test/support/vm/openldap/README.md +0 -32
  61. data/test/support/vm/openldap/Vagrantfile +0 -33
@@ -103,7 +103,7 @@ class Net::LDAP::Dataset < Hash
103
103
  # with the conversion of
104
104
  def from_entry(entry)
105
105
  dataset = Net::LDAP::Dataset.new
106
- hash = { }
106
+ hash = {}
107
107
  entry.each_attribute do |attribute, value|
108
108
  next if attribute == :dn
109
109
  hash[attribute] = value
@@ -165,4 +165,4 @@ class Net::LDAP::Dataset < Hash
165
165
  end
166
166
  end
167
167
 
168
- require 'net/ldap/entry' unless defined? Net::LDAP::Entry
168
+ require_relative 'entry' unless defined? Net::LDAP::Entry
@@ -57,19 +57,19 @@ class Net::LDAP::DN
57
57
  state = :key_oid
58
58
  key << char
59
59
  when ' ' then state = :key
60
- else raise "DN badly formed"
60
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
61
61
  end
62
62
  when :key_normal then
63
63
  case char
64
64
  when '=' then state = :value
65
65
  when 'a'..'z', 'A'..'Z', '0'..'9', '-', ' ' then key << char
66
- else raise "DN badly formed"
66
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
67
67
  end
68
68
  when :key_oid then
69
69
  case char
70
70
  when '=' then state = :value
71
71
  when '0'..'9', '.', ' ' then key << char
72
- else raise "DN badly formed"
72
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
73
73
  end
74
74
  when :value then
75
75
  case char
@@ -110,7 +110,7 @@ class Net::LDAP::DN
110
110
  when '0'..'9', 'a'..'f', 'A'..'F' then
111
111
  state = :value_normal
112
112
  value << "#{hex_buffer}#{char}".to_i(16).chr
113
- else raise "DN badly formed"
113
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
114
114
  end
115
115
  when :value_quoted then
116
116
  case char
@@ -132,7 +132,7 @@ class Net::LDAP::DN
132
132
  when '0'..'9', 'a'..'f', 'A'..'F' then
133
133
  state = :value_quoted
134
134
  value << "#{hex_buffer}#{char}".to_i(16).chr
135
- else raise "DN badly formed"
135
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
136
136
  end
137
137
  when :value_hexstring then
138
138
  case char
@@ -145,14 +145,14 @@ class Net::LDAP::DN
145
145
  yield key.string.strip, value.string.rstrip
146
146
  key = StringIO.new
147
147
  value = StringIO.new;
148
- else raise "DN badly formed"
148
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
149
149
  end
150
150
  when :value_hexstring_hex then
151
151
  case char
152
152
  when '0'..'9', 'a'..'f', 'A'..'F' then
153
153
  state = :value_hexstring
154
154
  value << char
155
- else raise "DN badly formed"
155
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
156
156
  end
157
157
  when :value_end then
158
158
  case char
@@ -162,18 +162,17 @@ class Net::LDAP::DN
162
162
  yield key.string.strip, value.string.rstrip
163
163
  key = StringIO.new
164
164
  value = StringIO.new;
165
- else raise "DN badly formed"
165
+ else raise Net::LDAP::InvalidDNError, "DN badly formed"
166
166
  end
167
- else raise "Fell out of state machine"
167
+ else raise Net::LDAP::InvalidDNError, "Fell out of state machine"
168
168
  end
169
169
  end
170
170
 
171
171
  # Last pair
172
- if [:value, :value_normal, :value_hexstring, :value_end].include? state
173
- yield key.string.strip, value.string.rstrip
174
- else
175
- raise "DN badly formed"
176
- end
172
+ raise Net::LDAP::InvalidDNError, "DN badly formed" unless
173
+ [:value, :value_normal, :value_hexstring, :value_end].include? state
174
+
175
+ yield key.string.strip, value.string.rstrip
177
176
  end
178
177
 
179
178
  ##
@@ -140,11 +140,10 @@ class Net::LDAP::Entry
140
140
  # arguments to the block: a Symbol giving the name of the attribute, and a
141
141
  # (possibly empty) \Array of data values.
142
142
  def each # :yields: attribute-name, data-values-array
143
- if block_given?
144
- attribute_names.each do|a|
145
- attr_name, values = a, self[a]
146
- yield attr_name, values
147
- end
143
+ return unless block_given?
144
+ attribute_names.each do|a|
145
+ attr_name, values = a, self[a]
146
+ yield attr_name, values
148
147
  end
149
148
  end
150
149
  alias_method :each_attribute, :each
@@ -190,4 +189,4 @@ class Net::LDAP::Entry
190
189
  private :setter?
191
190
  end # class Entry
192
191
 
193
- require 'net/ldap/dataset' unless defined? Net::LDAP::Dataset
192
+ require_relative 'dataset' unless defined? Net::LDAP::Dataset
@@ -60,6 +60,7 @@ class Net::LDAP
60
60
  class ResponseTypeInvalidError < Error; end
61
61
  class ResponseMissingOrInvalidError < Error; end
62
62
  class EmptyDNError < Error; end
63
+ class InvalidDNError < Error; end
63
64
  class HashTypeUnsupportedError < Error; end
64
65
  class OperatorError < Error; end
65
66
  class SubstringFilterError < Error; end
@@ -490,7 +490,7 @@ class Net::LDAP::Filter
490
490
  when :eq
491
491
  if @right == "*" # presence test
492
492
  @left.to_s.to_ber_contextspecific(7)
493
- elsif @right =~ /[*]/ # substring
493
+ elsif @right.to_s =~ /[*]/ # substring
494
494
  # Parsing substrings is a little tricky. We use String#split to
495
495
  # break a string into substrings delimited by the * (star)
496
496
  # character. But we also need to know whether there is a star at the
@@ -645,8 +645,15 @@ class Net::LDAP::Filter
645
645
 
646
646
  ##
647
647
  # Converts escaped characters (e.g., "\\28") to unescaped characters
648
+ # @note slawson20170317: Don't attempt to unescape 16 byte binary data which we assume are objectGUIDs
649
+ # The binary form of 5936AE79-664F-44EA-BCCB-5C39399514C6 triggers a BINARY -> UTF-8 conversion error
648
650
  def unescape(right)
649
- right.to_s.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") }
651
+ right = right.to_s
652
+ if right.length == 16 && right.encoding == Encoding::BINARY
653
+ right
654
+ else
655
+ right.to_s.gsub(/\\([a-fA-F\d]{2})/) { [$1.hex].pack("U") }
656
+ end
650
657
  end
651
658
  private :unescape
652
659
 
@@ -748,7 +755,7 @@ class Net::LDAP::Filter
748
755
  # This parses a given expression inside of parentheses.
749
756
  def parse_filter_branch(scanner)
750
757
  scanner.scan(/\s*/)
751
- if token = scanner.scan(/[-\w:.]*[\w]/)
758
+ if token = scanner.scan(/[-\w:.;]*[\w]/)
752
759
  scanner.scan(/\s*/)
753
760
  if op = scanner.scan(/<=|>=|!=|:=|=/)
754
761
  scanner.scan(/\s*/)
@@ -12,8 +12,8 @@ module Net::LDAP::Instrumentation
12
12
  def instrument(event, payload = {})
13
13
  payload = (payload || {}).dup
14
14
  if instrumentation_service
15
- instrumentation_service.instrument(event, payload) do |payload|
16
- payload[:result] = yield(payload) if block_given?
15
+ instrumentation_service.instrument(event, payload) do |instr_payload|
16
+ instr_payload[:result] = yield(instr_payload) if block_given?
17
17
  end
18
18
  else
19
19
  yield(payload) if block_given?
@@ -19,20 +19,18 @@ class Net::LDAP::Password
19
19
  # * Should we provide sha1 as a synonym for sha1? I vote no because then
20
20
  # should you also provide ssha1 for symmetry?
21
21
  #
22
- attribute_value = ""
23
22
  def generate(type, str)
24
23
  case type
25
24
  when :md5
26
- attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp!
25
+ '{MD5}' + Base64.strict_encode64(Digest::MD5.digest(str))
27
26
  when :sha
28
- attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp!
27
+ '{SHA}' + Base64.strict_encode64(Digest::SHA1.digest(str))
29
28
  when :ssha
30
29
  salt = SecureRandom.random_bytes(16)
31
- attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp!
30
+ '{SSHA}' + Base64.strict_encode64(Digest::SHA1.digest(str + salt) + salt)
32
31
  else
33
32
  raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})"
34
33
  end
35
- return attribute_value
36
34
  end
37
35
  end
38
36
  end
@@ -123,7 +123,7 @@ class Net::LDAP::PDU
123
123
  when ExtendedResponse
124
124
  parse_extended_response(ber_object[1])
125
125
  else
126
- raise LdapPduError.new("unknown pdu-type: #{@app_tag}")
126
+ raise Error.new("unknown pdu-type: #{@app_tag}")
127
127
  end
128
128
 
129
129
  parse_controls(ber_object[2]) if ber_object[2]
@@ -1,5 +1,5 @@
1
1
  module Net
2
2
  class LDAP
3
- VERSION = "0.14.0"
3
+ VERSION = "0.16.3"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
- require 'net/ldap/version'
2
+ require_relative 'ldap/version'
3
3
 
4
4
  # :stopdoc:
5
5
  module Net
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'net/ldap/version'
4
+ require_relative 'lib/net/ldap/version'
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{net-ldap}
@@ -30,8 +30,8 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).}
30
30
  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}
31
31
 
32
32
  s.add_development_dependency("flexmock", "~> 1.3")
33
- s.add_development_dependency("rake", "~> 10.0")
34
- s.add_development_dependency("rubocop", "~> 0.28.0")
33
+ s.add_development_dependency("rake", "~> 12.3.3")
34
+ s.add_development_dependency("rubocop", "~> 0.49.0")
35
35
  s.add_development_dependency("test-unit")
36
- s.add_development_dependency("byebug")
36
+ s.add_development_dependency("byebug") unless RUBY_PLATFORM == "java"
37
37
  end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+ # Usage: script/ldap-docker
3
+ #
4
+ # Starts a openldap docker container ready for integration tests
5
+
6
+ docker run --rm -ti \
7
+ --hostname ldap.example.org \
8
+ --env LDAP_TLS_VERIFY_CLIENT=try \
9
+ -p 389:389 -p 636:636 \
10
+ -v "$(pwd)"/test/fixtures/ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom \
11
+ --name my-openldap-container \
12
+ osixia/openldap:1.3.0 --copy-service --loglevel debug
@@ -95,7 +95,7 @@ class TestBEREncoding < Test::Unit::TestCase
95
95
  def test_encode_binary_data
96
96
  # This is used for searching for GUIDs in Active Directory
97
97
  assert_equal "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16".b,
98
- ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin
98
+ ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin
99
99
  end
100
100
 
101
101
  def test_non_utf8_encodable_strings
@@ -0,0 +1,18 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIC0zCCAlmgAwIBAgIUCfQ+m0pgZ/BjYAJvxrn/bdGNZokwCgYIKoZIzj0EAwMw
3
+ gZYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxBMUEgQ2FyIFdhc2gxJDAiBgNVBAsT
4
+ G0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgRGVwLjEUMBIGA1UEBxMLQWxidXF1ZXJx
5
+ dWUxEzARBgNVBAgTCk5ldyBNZXhpY28xHzAdBgNVBAMTFmRvY2tlci1saWdodC1i
6
+ YXNlaW1hZ2UwHhcNMTUxMjIzMTM1MzAwWhcNMjAxMjIxMTM1MzAwWjCBljELMAkG
7
+ A1UEBhMCVVMxFTATBgNVBAoTDEExQSBDYXIgV2FzaDEkMCIGA1UECxMbSW5mb3Jt
8
+ YXRpb24gVGVjaG5vbG9neSBEZXAuMRQwEgYDVQQHEwtBbGJ1cXVlcnF1ZTETMBEG
9
+ A1UECBMKTmV3IE1leGljbzEfMB0GA1UEAxMWZG9ja2VyLWxpZ2h0LWJhc2VpbWFn
10
+ ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMZf/12pupAgl8Sm+j8GmjNeNbSFAZWW
11
+ oTmIvf2Mu4LWPHy4bTldkQgHUbBpT3xWz8f0lB/ru7596CHsGoL2A28hxuclq5hb
12
+ Ux1yrIt3bJIY3TuiX25HGTe6kGCJPB1aLaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG
13
+ A1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFE+l6XolXDAYnGLTl4W6ULKHrm74
14
+ MB8GA1UdIwQYMBaAFE+l6XolXDAYnGLTl4W6ULKHrm74MAoGCCqGSM49BAMDA2gA
15
+ MGUCMQCXLZj8okyxW6UTL7hribUUbu63PbjuwIXnwi420DdNsvA9A7fcQEXScWFL
16
+ XAGC8rkCMGcqwXZPSRfwuI9r+R11gTrP92hnaVxs9sjRikctpkQpOyNlIXFPopFK
17
+ 8FdfWPypvA==
18
+ -----END CERTIFICATE-----
@@ -1,19 +1,18 @@
1
- dn: cn=module,cn=config
2
- cn: module
3
- objectClass: olcModuleList
4
- objectClass: top
5
- olcModulePath: /usr/lib/ldap
6
- olcModuleLoad: retcode.la
1
+ dn: cn=module{0},cn=config
2
+ changetype: modify
3
+ add: olcModuleLoad
4
+ olcModuleLoad: retcode
7
5
 
8
6
  # source: http://www.opensource.apple.com/source/OpenLDAP/OpenLDAP-186/OpenLDAP/tests/data/retcode.conf?txt
9
7
 
10
- dn: olcOverlay={2}retcode,olcDatabase={1}hdb,cn=config
8
+ dn: olcOverlay={2}retcode,olcDatabase={1}{{ LDAP_BACKEND }},cn=config
9
+ changetype: add
11
10
  objectClass: olcConfig
12
11
  objectClass: olcRetcodeConfig
13
12
  objectClass: olcOverlayConfig
14
13
  objectClass: top
15
14
  olcOverlay: retcode
16
- olcRetcodeParent: ou=Retcodes,dc=rubyldap,dc=com
15
+ olcRetcodeParent: ou=Retcodes,dc=example,dc=org
17
16
  olcRetcodeInDir: TRUE
18
17
  olcRetcodeSleep: 0
19
18
  olcRetcodeItem: "cn=success" 0x00
@@ -0,0 +1,374 @@
1
+ dn: ou=People,dc=example,dc=org
2
+ objectClass: top
3
+ objectClass: organizationalUnit
4
+ ou: People
5
+
6
+ dn: ou=Groups,dc=example,dc=org
7
+ objectClass: top
8
+ objectClass: organizationalUnit
9
+ ou: Groups
10
+
11
+ # Directory Superuser
12
+ dn: uid=admin,dc=example,dc=org
13
+ uid: admin
14
+ cn: system administrator
15
+ sn: administrator
16
+ objectClass: top
17
+ objectClass: person
18
+ objectClass: organizationalPerson
19
+ objectClass: inetOrgPerson
20
+ displayName: Directory Superuser
21
+ userPassword: passworD1
22
+
23
+ # Users 1-10
24
+
25
+ dn: uid=user1,ou=People,dc=example,dc=org
26
+ uid: user1
27
+ cn: user1
28
+ sn: user1
29
+ objectClass: top
30
+ objectClass: person
31
+ objectClass: organizationalPerson
32
+ objectClass: inetOrgPerson
33
+ userPassword: passworD1
34
+ mail: user1@rubyldap.com
35
+
36
+ dn: uid=user2,ou=People,dc=example,dc=org
37
+ uid: user2
38
+ cn: user2
39
+ sn: user2
40
+ objectClass: top
41
+ objectClass: person
42
+ objectClass: organizationalPerson
43
+ objectClass: inetOrgPerson
44
+ userPassword: passworD1
45
+ mail: user2@rubyldap.com
46
+
47
+ dn: uid=user3,ou=People,dc=example,dc=org
48
+ uid: user3
49
+ cn: user3
50
+ sn: user3
51
+ objectClass: top
52
+ objectClass: person
53
+ objectClass: organizationalPerson
54
+ objectClass: inetOrgPerson
55
+ userPassword: passworD1
56
+ mail: user3@rubyldap.com
57
+
58
+ dn: uid=user4,ou=People,dc=example,dc=org
59
+ uid: user4
60
+ cn: user4
61
+ sn: user4
62
+ objectClass: top
63
+ objectClass: person
64
+ objectClass: organizationalPerson
65
+ objectClass: inetOrgPerson
66
+ userPassword: passworD1
67
+ mail: user4@rubyldap.com
68
+
69
+ dn: uid=user5,ou=People,dc=example,dc=org
70
+ uid: user5
71
+ cn: user5
72
+ sn: user5
73
+ objectClass: top
74
+ objectClass: person
75
+ objectClass: organizationalPerson
76
+ objectClass: inetOrgPerson
77
+ userPassword: passworD1
78
+ mail: user5@rubyldap.com
79
+
80
+ dn: uid=user6,ou=People,dc=example,dc=org
81
+ uid: user6
82
+ cn: user6
83
+ sn: user6
84
+ objectClass: top
85
+ objectClass: person
86
+ objectClass: organizationalPerson
87
+ objectClass: inetOrgPerson
88
+ userPassword: passworD1
89
+ mail: user6@rubyldap.com
90
+
91
+ dn: uid=user7,ou=People,dc=example,dc=org
92
+ uid: user7
93
+ cn: user7
94
+ sn: user7
95
+ objectClass: top
96
+ objectClass: person
97
+ objectClass: organizationalPerson
98
+ objectClass: inetOrgPerson
99
+ userPassword: passworD1
100
+ mail: user7@rubyldap.com
101
+
102
+ dn: uid=user8,ou=People,dc=example,dc=org
103
+ uid: user8
104
+ cn: user8
105
+ sn: user8
106
+ objectClass: top
107
+ objectClass: person
108
+ objectClass: organizationalPerson
109
+ objectClass: inetOrgPerson
110
+ userPassword: passworD1
111
+ mail: user8@rubyldap.com
112
+
113
+ dn: uid=user9,ou=People,dc=example,dc=org
114
+ uid: user9
115
+ cn: user9
116
+ sn: user9
117
+ objectClass: top
118
+ objectClass: person
119
+ objectClass: organizationalPerson
120
+ objectClass: inetOrgPerson
121
+ userPassword: passworD1
122
+ mail: user9@rubyldap.com
123
+
124
+ dn: uid=user10,ou=People,dc=example,dc=org
125
+ uid: user10
126
+ cn: user10
127
+ sn: user10
128
+ objectClass: top
129
+ objectClass: person
130
+ objectClass: organizationalPerson
131
+ objectClass: inetOrgPerson
132
+ userPassword: passworD1
133
+ mail: user10@rubyldap.com
134
+
135
+ # Emailless User
136
+
137
+ dn: uid=emailless-user1,ou=People,dc=example,dc=org
138
+ uid: emailless-user1
139
+ cn: emailless-user1
140
+ sn: emailless-user1
141
+ objectClass: top
142
+ objectClass: person
143
+ objectClass: organizationalPerson
144
+ objectClass: inetOrgPerson
145
+ userPassword: passworD1
146
+
147
+ # Groupless User
148
+
149
+ dn: uid=groupless-user1,ou=People,dc=example,dc=org
150
+ uid: groupless-user1
151
+ cn: groupless-user1
152
+ sn: groupless-user1
153
+ objectClass: top
154
+ objectClass: person
155
+ objectClass: organizationalPerson
156
+ objectClass: inetOrgPerson
157
+ userPassword: passworD1
158
+
159
+ # Admin User
160
+
161
+ dn: uid=admin1,ou=People,dc=example,dc=org
162
+ uid: admin1
163
+ cn: admin1
164
+ sn: admin1
165
+ objectClass: top
166
+ objectClass: person
167
+ objectClass: organizationalPerson
168
+ objectClass: inetOrgPerson
169
+ userPassword: passworD1
170
+ mail: admin1@rubyldap.com
171
+
172
+ # Groups
173
+
174
+ dn: cn=ghe-users,ou=Groups,dc=example,dc=org
175
+ cn: ghe-users
176
+ objectClass: groupOfNames
177
+ member: uid=user1,ou=People,dc=example,dc=org
178
+ member: uid=emailless-user1,ou=People,dc=example,dc=org
179
+
180
+ dn: cn=all-users,ou=Groups,dc=example,dc=org
181
+ cn: all-users
182
+ objectClass: groupOfNames
183
+ member: cn=ghe-users,ou=Groups,dc=example,dc=org
184
+ member: uid=user1,ou=People,dc=example,dc=org
185
+ member: uid=user2,ou=People,dc=example,dc=org
186
+ member: uid=user3,ou=People,dc=example,dc=org
187
+ member: uid=user4,ou=People,dc=example,dc=org
188
+ member: uid=user5,ou=People,dc=example,dc=org
189
+ member: uid=user6,ou=People,dc=example,dc=org
190
+ member: uid=user7,ou=People,dc=example,dc=org
191
+ member: uid=user8,ou=People,dc=example,dc=org
192
+ member: uid=user9,ou=People,dc=example,dc=org
193
+ member: uid=user10,ou=People,dc=example,dc=org
194
+ member: uid=emailless-user1,ou=People,dc=example,dc=org
195
+
196
+ dn: cn=ghe-admins,ou=Groups,dc=example,dc=org
197
+ cn: ghe-admins
198
+ objectClass: groupOfNames
199
+ member: uid=admin1,ou=People,dc=example,dc=org
200
+
201
+ dn: cn=all-admins,ou=Groups,dc=example,dc=org
202
+ cn: all-admins
203
+ objectClass: groupOfNames
204
+ member: cn=ghe-admins,ou=Groups,dc=example,dc=org
205
+ member: uid=admin1,ou=People,dc=example,dc=org
206
+
207
+ dn: cn=n-member-group10,ou=Groups,dc=example,dc=org
208
+ cn: n-member-group10
209
+ objectClass: groupOfNames
210
+ member: uid=user1,ou=People,dc=example,dc=org
211
+ member: uid=user2,ou=People,dc=example,dc=org
212
+ member: uid=user3,ou=People,dc=example,dc=org
213
+ member: uid=user4,ou=People,dc=example,dc=org
214
+ member: uid=user5,ou=People,dc=example,dc=org
215
+ member: uid=user6,ou=People,dc=example,dc=org
216
+ member: uid=user7,ou=People,dc=example,dc=org
217
+ member: uid=user8,ou=People,dc=example,dc=org
218
+ member: uid=user9,ou=People,dc=example,dc=org
219
+ member: uid=user10,ou=People,dc=example,dc=org
220
+
221
+ dn: cn=nested-group1,ou=Groups,dc=example,dc=org
222
+ cn: nested-group1
223
+ objectClass: groupOfNames
224
+ member: uid=user1,ou=People,dc=example,dc=org
225
+ member: uid=user2,ou=People,dc=example,dc=org
226
+ member: uid=user3,ou=People,dc=example,dc=org
227
+ member: uid=user4,ou=People,dc=example,dc=org
228
+ member: uid=user5,ou=People,dc=example,dc=org
229
+
230
+ dn: cn=nested-group2,ou=Groups,dc=example,dc=org
231
+ cn: nested-group2
232
+ objectClass: groupOfNames
233
+ member: uid=user6,ou=People,dc=example,dc=org
234
+ member: uid=user7,ou=People,dc=example,dc=org
235
+ member: uid=user8,ou=People,dc=example,dc=org
236
+ member: uid=user9,ou=People,dc=example,dc=org
237
+ member: uid=user10,ou=People,dc=example,dc=org
238
+
239
+ dn: cn=nested-groups,ou=Groups,dc=example,dc=org
240
+ cn: nested-groups
241
+ objectClass: groupOfNames
242
+ member: cn=nested-group1,ou=Groups,dc=example,dc=org
243
+ member: cn=nested-group2,ou=Groups,dc=example,dc=org
244
+
245
+ dn: cn=n-member-nested-group1,ou=Groups,dc=example,dc=org
246
+ cn: n-member-nested-group1
247
+ objectClass: groupOfNames
248
+ member: cn=nested-group1,ou=Groups,dc=example,dc=org
249
+
250
+ dn: cn=deeply-nested-group0.0.0,ou=Groups,dc=example,dc=org
251
+ cn: deeply-nested-group0.0.0
252
+ objectClass: groupOfNames
253
+ member: uid=user1,ou=People,dc=example,dc=org
254
+ member: uid=user2,ou=People,dc=example,dc=org
255
+ member: uid=user3,ou=People,dc=example,dc=org
256
+ member: uid=user4,ou=People,dc=example,dc=org
257
+ member: uid=user5,ou=People,dc=example,dc=org
258
+
259
+ dn: cn=deeply-nested-group0.0.1,ou=Groups,dc=example,dc=org
260
+ cn: deeply-nested-group0.0.1
261
+ objectClass: groupOfNames
262
+ member: uid=user6,ou=People,dc=example,dc=org
263
+ member: uid=user7,ou=People,dc=example,dc=org
264
+ member: uid=user8,ou=People,dc=example,dc=org
265
+ member: uid=user9,ou=People,dc=example,dc=org
266
+ member: uid=user10,ou=People,dc=example,dc=org
267
+
268
+ dn: cn=deeply-nested-group0.0,ou=Groups,dc=example,dc=org
269
+ cn: deeply-nested-group0.0
270
+ objectClass: groupOfNames
271
+ member: cn=deeply-nested-group0.0.0,ou=Groups,dc=example,dc=org
272
+ member: cn=deeply-nested-group0.0.1,ou=Groups,dc=example,dc=org
273
+
274
+ dn: cn=deeply-nested-group0,ou=Groups,dc=example,dc=org
275
+ cn: deeply-nested-group0
276
+ objectClass: groupOfNames
277
+ member: cn=deeply-nested-group0.0,ou=Groups,dc=example,dc=org
278
+
279
+ dn: cn=deeply-nested-groups,ou=Groups,dc=example,dc=org
280
+ cn: deeply-nested-groups
281
+ objectClass: groupOfNames
282
+ member: cn=deeply-nested-group0,ou=Groups,dc=example,dc=org
283
+
284
+ dn: cn=n-depth-nested-group1,ou=Groups,dc=example,dc=org
285
+ cn: n-depth-nested-group1
286
+ objectClass: groupOfNames
287
+ member: cn=nested-group1,ou=Groups,dc=example,dc=org
288
+
289
+ dn: cn=n-depth-nested-group2,ou=Groups,dc=example,dc=org
290
+ cn: n-depth-nested-group2
291
+ objectClass: groupOfNames
292
+ member: cn=n-depth-nested-group1,ou=Groups,dc=example,dc=org
293
+
294
+ dn: cn=n-depth-nested-group3,ou=Groups,dc=example,dc=org
295
+ cn: n-depth-nested-group3
296
+ objectClass: groupOfNames
297
+ member: cn=n-depth-nested-group2,ou=Groups,dc=example,dc=org
298
+
299
+ dn: cn=n-depth-nested-group4,ou=Groups,dc=example,dc=org
300
+ cn: n-depth-nested-group4
301
+ objectClass: groupOfNames
302
+ member: cn=n-depth-nested-group3,ou=Groups,dc=example,dc=org
303
+
304
+ dn: cn=n-depth-nested-group5,ou=Groups,dc=example,dc=org
305
+ cn: n-depth-nested-group5
306
+ objectClass: groupOfNames
307
+ member: cn=n-depth-nested-group4,ou=Groups,dc=example,dc=org
308
+
309
+ dn: cn=n-depth-nested-group6,ou=Groups,dc=example,dc=org
310
+ cn: n-depth-nested-group6
311
+ objectClass: groupOfNames
312
+ member: cn=n-depth-nested-group5,ou=Groups,dc=example,dc=org
313
+
314
+ dn: cn=n-depth-nested-group7,ou=Groups,dc=example,dc=org
315
+ cn: n-depth-nested-group7
316
+ objectClass: groupOfNames
317
+ member: cn=n-depth-nested-group6,ou=Groups,dc=example,dc=org
318
+
319
+ dn: cn=n-depth-nested-group8,ou=Groups,dc=example,dc=org
320
+ cn: n-depth-nested-group8
321
+ objectClass: groupOfNames
322
+ member: cn=n-depth-nested-group7,ou=Groups,dc=example,dc=org
323
+
324
+ dn: cn=n-depth-nested-group9,ou=Groups,dc=example,dc=org
325
+ cn: n-depth-nested-group9
326
+ objectClass: groupOfNames
327
+ member: cn=n-depth-nested-group8,ou=Groups,dc=example,dc=org
328
+
329
+ dn: cn=head-group,ou=Groups,dc=example,dc=org
330
+ cn: head-group
331
+ objectClass: groupOfNames
332
+ member: cn=tail-group,ou=Groups,dc=example,dc=org
333
+ member: uid=user1,ou=People,dc=example,dc=org
334
+ member: uid=user2,ou=People,dc=example,dc=org
335
+ member: uid=user3,ou=People,dc=example,dc=org
336
+ member: uid=user4,ou=People,dc=example,dc=org
337
+ member: uid=user5,ou=People,dc=example,dc=org
338
+
339
+ dn: cn=tail-group,ou=Groups,dc=example,dc=org
340
+ cn: tail-group
341
+ objectClass: groupOfNames
342
+ member: cn=head-group,ou=Groups,dc=example,dc=org
343
+ member: uid=user6,ou=People,dc=example,dc=org
344
+ member: uid=user7,ou=People,dc=example,dc=org
345
+ member: uid=user8,ou=People,dc=example,dc=org
346
+ member: uid=user9,ou=People,dc=example,dc=org
347
+ member: uid=user10,ou=People,dc=example,dc=org
348
+
349
+ dn: cn=recursively-nested-groups,ou=Groups,dc=example,dc=org
350
+ cn: recursively-nested-groups
351
+ objectClass: groupOfNames
352
+ member: cn=head-group,ou=Groups,dc=example,dc=org
353
+ member: cn=tail-group,ou=Groups,dc=example,dc=org
354
+
355
+ # posixGroup
356
+
357
+ dn: cn=posix-group1,ou=Groups,dc=example,dc=org
358
+ cn: posix-group1
359
+ objectClass: posixGroup
360
+ gidNumber: 1001
361
+ memberUid: user1
362
+ memberUid: user2
363
+ memberUid: user3
364
+ memberUid: user4
365
+ memberUid: user5
366
+
367
+ # missing members
368
+
369
+ dn: cn=missing-users,ou=Groups,dc=example,dc=org
370
+ cn: missing-users
371
+ objectClass: groupOfNames
372
+ member: uid=user1,ou=People,dc=example,dc=org
373
+ member: uid=user2,ou=People,dc=example,dc=org
374
+ member: uid=nonexistent-user,ou=People,dc=example,dc=org