rom-ldap 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +251 -0
- data/CONTRIBUTING.md +18 -0
- data/README.md +172 -0
- data/TODO.md +33 -0
- data/config/responses.yml +328 -0
- data/lib/dry/monitor/ldap/colorizers/default.rb +17 -0
- data/lib/dry/monitor/ldap/colorizers/rouge.rb +31 -0
- data/lib/dry/monitor/ldap/logger.rb +58 -0
- data/lib/rom-ldap.rb +1 -0
- data/lib/rom/ldap.rb +22 -0
- data/lib/rom/ldap/alias.rb +30 -0
- data/lib/rom/ldap/associations.rb +6 -0
- data/lib/rom/ldap/associations/core.rb +23 -0
- data/lib/rom/ldap/associations/many_to_many.rb +18 -0
- data/lib/rom/ldap/associations/many_to_one.rb +22 -0
- data/lib/rom/ldap/associations/one_to_many.rb +32 -0
- data/lib/rom/ldap/associations/one_to_one.rb +19 -0
- data/lib/rom/ldap/associations/self_ref.rb +35 -0
- data/lib/rom/ldap/attribute.rb +327 -0
- data/lib/rom/ldap/client.rb +185 -0
- data/lib/rom/ldap/client/authentication.rb +118 -0
- data/lib/rom/ldap/client/operations.rb +233 -0
- data/lib/rom/ldap/commands.rb +6 -0
- data/lib/rom/ldap/commands/create.rb +41 -0
- data/lib/rom/ldap/commands/delete.rb +17 -0
- data/lib/rom/ldap/commands/update.rb +35 -0
- data/lib/rom/ldap/constants.rb +193 -0
- data/lib/rom/ldap/dataset.rb +286 -0
- data/lib/rom/ldap/dataset/conversion.rb +62 -0
- data/lib/rom/ldap/dataset/dsl.rb +299 -0
- data/lib/rom/ldap/dataset/persistence.rb +44 -0
- data/lib/rom/ldap/directory.rb +126 -0
- data/lib/rom/ldap/directory/capabilities.rb +71 -0
- data/lib/rom/ldap/directory/entry.rb +200 -0
- data/lib/rom/ldap/directory/env.rb +155 -0
- data/lib/rom/ldap/directory/operations.rb +282 -0
- data/lib/rom/ldap/directory/password.rb +122 -0
- data/lib/rom/ldap/directory/root.rb +187 -0
- data/lib/rom/ldap/directory/tokenization.rb +66 -0
- data/lib/rom/ldap/directory/transactions.rb +31 -0
- data/lib/rom/ldap/directory/vendors/active_directory.rb +129 -0
- data/lib/rom/ldap/directory/vendors/apache_ds.rb +27 -0
- data/lib/rom/ldap/directory/vendors/e_directory.rb +16 -0
- data/lib/rom/ldap/directory/vendors/open_directory.rb +12 -0
- data/lib/rom/ldap/directory/vendors/open_dj.rb +25 -0
- data/lib/rom/ldap/directory/vendors/open_ldap.rb +35 -0
- data/lib/rom/ldap/directory/vendors/three_eight_nine.rb +16 -0
- data/lib/rom/ldap/directory/vendors/unknown.rb +22 -0
- data/lib/rom/ldap/dsl.rb +76 -0
- data/lib/rom/ldap/errors.rb +47 -0
- data/lib/rom/ldap/expression.rb +77 -0
- data/lib/rom/ldap/expression_encoder.rb +174 -0
- data/lib/rom/ldap/extensions.rb +50 -0
- data/lib/rom/ldap/extensions/active_support_notifications.rb +26 -0
- data/lib/rom/ldap/extensions/compatibility.rb +11 -0
- data/lib/rom/ldap/extensions/dsml.rb +165 -0
- data/lib/rom/ldap/extensions/msgpack.rb +23 -0
- data/lib/rom/ldap/extensions/optimised_json.rb +25 -0
- data/lib/rom/ldap/extensions/rails_log_subscriber.rb +38 -0
- data/lib/rom/ldap/formatter.rb +26 -0
- data/lib/rom/ldap/functions.rb +207 -0
- data/lib/rom/ldap/gateway.rb +145 -0
- data/lib/rom/ldap/ldif.rb +74 -0
- data/lib/rom/ldap/ldif/exporter.rb +77 -0
- data/lib/rom/ldap/ldif/importer.rb +95 -0
- data/lib/rom/ldap/mapper_compiler.rb +19 -0
- data/lib/rom/ldap/matchers.rb +69 -0
- data/lib/rom/ldap/message_queue.rb +7 -0
- data/lib/rom/ldap/oid.rb +101 -0
- data/lib/rom/ldap/parsers/abstract_syntax.rb +91 -0
- data/lib/rom/ldap/parsers/attribute.rb +290 -0
- data/lib/rom/ldap/parsers/filter_syntax.rb +133 -0
- data/lib/rom/ldap/pdu.rb +285 -0
- data/lib/rom/ldap/plugin/pagination.rb +145 -0
- data/lib/rom/ldap/plugins.rb +7 -0
- data/lib/rom/ldap/projection_dsl.rb +38 -0
- data/lib/rom/ldap/relation.rb +135 -0
- data/lib/rom/ldap/relation/exporting.rb +72 -0
- data/lib/rom/ldap/relation/reading.rb +461 -0
- data/lib/rom/ldap/relation/writing.rb +64 -0
- data/lib/rom/ldap/responses.rb +17 -0
- data/lib/rom/ldap/restriction_dsl.rb +45 -0
- data/lib/rom/ldap/schema.rb +123 -0
- data/lib/rom/ldap/schema/attributes_inferrer.rb +59 -0
- data/lib/rom/ldap/schema/dsl.rb +13 -0
- data/lib/rom/ldap/schema/inferrer.rb +50 -0
- data/lib/rom/ldap/schema/type_builder.rb +133 -0
- data/lib/rom/ldap/scope.rb +19 -0
- data/lib/rom/ldap/search_request.rb +249 -0
- data/lib/rom/ldap/socket.rb +210 -0
- data/lib/rom/ldap/tasks/ldap.rake +103 -0
- data/lib/rom/ldap/tasks/ldif.rake +80 -0
- data/lib/rom/ldap/transaction.rb +29 -0
- data/lib/rom/ldap/type_map.rb +88 -0
- data/lib/rom/ldap/types.rb +158 -0
- data/lib/rom/ldap/version.rb +17 -0
- data/lib/rom/plugins/relation/ldap/active_directory.rb +182 -0
- data/lib/rom/plugins/relation/ldap/auto_restrictions.rb +69 -0
- data/lib/rom/plugins/relation/ldap/e_directory.rb +27 -0
- data/lib/rom/plugins/relation/ldap/instrumentation.rb +35 -0
- data/lib/rouge/lexers/ldap.rb +72 -0
- data/lib/rouge/themes/ldap.rb +49 -0
- metadata +231 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/sha1'
|
4
|
+
require 'digest/sha2'
|
5
|
+
require 'digest/md5'
|
6
|
+
require 'base64'
|
7
|
+
require 'securerandom'
|
8
|
+
|
9
|
+
# sha2-512 512bit or 64bytes
|
10
|
+
# sha 160bits or 20bytes
|
11
|
+
#
|
12
|
+
module ROM
|
13
|
+
module LDAP
|
14
|
+
class Directory
|
15
|
+
|
16
|
+
# @abstract
|
17
|
+
# Encode and validate passwords using md5, sha or ssha.
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
class Password
|
21
|
+
|
22
|
+
# Generate an ecrypted password.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Password.generate(:ssha, 'secret magic word')
|
26
|
+
#
|
27
|
+
# @param type [Symbol] Encryption type. [:md5, :sha, :ssha].
|
28
|
+
# @param password [String] Plain text password to be encrypted.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
#
|
32
|
+
# @raise [PasswordError]
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
def self.generate(type, password, salt = secure_salt)
|
36
|
+
raise PasswordError, 'No password supplied' if password.nil?
|
37
|
+
|
38
|
+
case type
|
39
|
+
when :md5 then _encode(type, md5(password))
|
40
|
+
when :sha then _encode(type, sha(password))
|
41
|
+
when :ssha then _encode(type, ssha(password, salt))
|
42
|
+
when :ssha512 then _encode(type, ssha512(password, salt))
|
43
|
+
else
|
44
|
+
raise PasswordError, "Unsupported encryption type (#{type})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.check_ssha512(password, encrypted)
|
49
|
+
decoded = Base64.decode64(encrypted.gsub(/^{SSHA512}/, EMPTY_STRING))
|
50
|
+
# hash = decoded[0..64]
|
51
|
+
salt = decoded[64..-1]
|
52
|
+
_encode(:ssha512, ssha512(password, salt)) == encrypted
|
53
|
+
end
|
54
|
+
|
55
|
+
# Validate plain password against encrypted SSHA password.
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
def self.check_ssha(password, encrypted)
|
61
|
+
decoded = Base64.decode64(encrypted.gsub(/^{SSHA}/, EMPTY_STRING))
|
62
|
+
# hash = decoded[0..20]
|
63
|
+
salt = decoded[20..-1]
|
64
|
+
_encode(:ssha, ssha(password, salt)) == encrypted
|
65
|
+
end
|
66
|
+
|
67
|
+
private_class_method
|
68
|
+
|
69
|
+
# @return [String] Prepend type to encrypted string.
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
def self._encode(type, encrypted)
|
73
|
+
"{#{type.upcase}}" + Base64.strict_encode64(encrypted).chomp
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generate salt.
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
def self.secure_salt
|
80
|
+
SecureRandom.random_bytes(16)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param str [String]
|
84
|
+
#
|
85
|
+
# @return [String] MD5 digest.
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
def self.md5(str)
|
89
|
+
Digest::MD5.digest(str)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param str [String]
|
93
|
+
# @param salt [String]
|
94
|
+
#
|
95
|
+
# @return [String] SHA1 digest with salt.
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def self.ssha(str, salt)
|
99
|
+
Digest::SHA1.digest(str + salt) + salt
|
100
|
+
end
|
101
|
+
|
102
|
+
# @param str [String]
|
103
|
+
#
|
104
|
+
# @return [String] SHA1 digest without salt.
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
def self.sha(str)
|
108
|
+
Digest::SHA1.digest(str)
|
109
|
+
end
|
110
|
+
|
111
|
+
# "{SSHA512}A1lCCGYzUEJ5/qQCrFUAztLVaTaWv959RnpzaOsWB9Ij4CBCeNh6i4XrZzrvwUMM/AWbEb8Gjc7FWOBSPnkRuHsexjzeQImm"
|
112
|
+
# initial
|
113
|
+
#
|
114
|
+
def self.ssha512(str, salt)
|
115
|
+
Digest::SHA512.digest(str + salt) + salt
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module LDAP
|
5
|
+
class Directory
|
6
|
+
|
7
|
+
module Root
|
8
|
+
# Identify the LDAP server vendor, type determines vendor extension to load.
|
9
|
+
#
|
10
|
+
# @see https://ldapwiki.com/wiki/Determine%20LDAP%20Server%20Vendor
|
11
|
+
#
|
12
|
+
# @return [Symbol]
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
def type
|
16
|
+
case root.first('vendorName')
|
17
|
+
when /389/ then :three_eight_nine
|
18
|
+
when /Apache/ then :apache_ds
|
19
|
+
when /Apple/ then :open_directory
|
20
|
+
when /ForgeRock/ then :open_dj
|
21
|
+
when /IBM/ then :ibm
|
22
|
+
when /Netscape/ then :netscape
|
23
|
+
when /Novell/ then :e_directory
|
24
|
+
when /Oracle/ then :open_ds
|
25
|
+
when /Sun/ then :sun_microsystems
|
26
|
+
when nil
|
27
|
+
return :active_directory if ad?
|
28
|
+
return :open_ldap if od?
|
29
|
+
else
|
30
|
+
:unknown
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
def vendor_name
|
38
|
+
root.first('vendorName')
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
def vendor_version
|
45
|
+
root.first('vendorVersion')
|
46
|
+
end
|
47
|
+
|
48
|
+
# @example
|
49
|
+
# [ 'Apple', '510.30' ]
|
50
|
+
# [ 'Apache Software Foundation', '2.0.0-M24' ]
|
51
|
+
#
|
52
|
+
# @return [Array<String>]
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
def vendor
|
56
|
+
[vendor_name, vendor_version]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Distinguished name of subschema
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
#
|
63
|
+
# @api public
|
64
|
+
def sub_schema_entry
|
65
|
+
root.first('subschemaSubentry')
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Array<String>] Object classes known by directory
|
69
|
+
#
|
70
|
+
# @api public
|
71
|
+
def schema_object_classes
|
72
|
+
sub_schema['objectClasses'].sort
|
73
|
+
end
|
74
|
+
|
75
|
+
# Query directory for all known attribute types
|
76
|
+
#
|
77
|
+
# @return [Array<String>] Attribute types known by directory
|
78
|
+
#
|
79
|
+
# @api public
|
80
|
+
def schema_attribute_types
|
81
|
+
sub_schema['attributeTypes'].sort
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array<String>]
|
85
|
+
#
|
86
|
+
# @api public
|
87
|
+
def supported_extensions
|
88
|
+
root['supportedExtension'].sort
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [Array<String>]
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
def supported_controls
|
95
|
+
root['supportedControl'].sort
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Array<String>]
|
99
|
+
#
|
100
|
+
# @api public
|
101
|
+
def supported_mechanisms
|
102
|
+
root['supportedSASLMechanisms'].sort
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [Array<String>]
|
106
|
+
#
|
107
|
+
# @api public
|
108
|
+
def supported_features
|
109
|
+
root['supportedFeatures'].sort
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Array<Integer>]
|
113
|
+
#
|
114
|
+
# @api public
|
115
|
+
def supported_versions
|
116
|
+
root['supportedLDAPVersion'].sort.map(&:to_i)
|
117
|
+
end
|
118
|
+
|
119
|
+
# @return [String]
|
120
|
+
#
|
121
|
+
# @api public
|
122
|
+
def contexts
|
123
|
+
root['namingContexts'].sort
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Representation of directory RootDSE
|
129
|
+
#
|
130
|
+
# @see https://ldapwiki.com/wiki/Retrieving%20RootDSE
|
131
|
+
#
|
132
|
+
# @return [Directory::Entry]
|
133
|
+
#
|
134
|
+
# @raise [ResponseError]
|
135
|
+
#
|
136
|
+
# @api private
|
137
|
+
def root
|
138
|
+
@root ||= query(
|
139
|
+
base: EMPTY_STRING,
|
140
|
+
scope: SCOPE_BASE,
|
141
|
+
attributes: ALL_ATTRS
|
142
|
+
).first
|
143
|
+
|
144
|
+
@root || raise(ResponseError, 'Directory root failed to load')
|
145
|
+
end
|
146
|
+
|
147
|
+
# Representation of directory SubSchema
|
148
|
+
#
|
149
|
+
# @return [Directory::Entry]
|
150
|
+
#
|
151
|
+
# @raise [ResponseError]
|
152
|
+
#
|
153
|
+
# @api private
|
154
|
+
def sub_schema
|
155
|
+
@sub_schema ||= query(
|
156
|
+
base: sub_schema_entry,
|
157
|
+
scope: SCOPE_BASE,
|
158
|
+
attributes: %w[objectClasses attributeTypes],
|
159
|
+
filter: '(objectClass=subschema)',
|
160
|
+
max_results: 1
|
161
|
+
).first
|
162
|
+
|
163
|
+
@sub_schema || raise(ResponseError, 'Directory schema failed to load')
|
164
|
+
end
|
165
|
+
|
166
|
+
# Check if vendor identifies as ActiveDirectory
|
167
|
+
#
|
168
|
+
# @return [Boolean]
|
169
|
+
#
|
170
|
+
# @api private
|
171
|
+
def ad?
|
172
|
+
!root['forestFunctionality'].nil?
|
173
|
+
end
|
174
|
+
|
175
|
+
# Check if vendor identifies as OpenLDAP
|
176
|
+
#
|
177
|
+
# @return [Boolean]
|
178
|
+
#
|
179
|
+
# @api private
|
180
|
+
def od?
|
181
|
+
root['objectClass']&.include?('OpenLDAProotDSE')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rom/ldap/parsers/abstract_syntax'
|
4
|
+
require 'rom/ldap/parsers/filter_syntax'
|
5
|
+
require 'rom/ldap/parsers/attribute'
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
module LDAP
|
9
|
+
class Directory
|
10
|
+
|
11
|
+
# Parsing Formats
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
module Tokenization
|
15
|
+
# Allows adapters that subclass Directory to use custom parsers.
|
16
|
+
# Extends the class with filter abstraction behavior.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def self.included(klass)
|
20
|
+
klass.class_eval do
|
21
|
+
extend Dry::Core::ClassAttributes
|
22
|
+
|
23
|
+
defines :attribute_class
|
24
|
+
attribute_class Parsers::Attribute
|
25
|
+
|
26
|
+
defines :filter_class
|
27
|
+
filter_class Parsers::FilterSyntax
|
28
|
+
|
29
|
+
defines :ast_class
|
30
|
+
ast_class Parsers::AbstractSyntax
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Convert abstract criteria or LDAP filter into an expression object.
|
37
|
+
# Check for parsed attributes to prevent recursion.
|
38
|
+
#
|
39
|
+
# @param input [Array, String] RFC2254 or AST
|
40
|
+
#
|
41
|
+
def to_expression(input)
|
42
|
+
attrs = !@attribute_types.nil? ? attribute_types : EMPTY_ARRAY
|
43
|
+
|
44
|
+
# Filter > AST
|
45
|
+
unless input.is_a?(Array)
|
46
|
+
input = self.class.filter_class.new(input, attrs).call
|
47
|
+
end
|
48
|
+
|
49
|
+
# AST > Expression
|
50
|
+
self.class.ast_class.new(input, attrs).call
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create parsed attribute from definiton.
|
54
|
+
#
|
55
|
+
# @param attr_def [String]
|
56
|
+
#
|
57
|
+
# @return [Hash]
|
58
|
+
#
|
59
|
+
def to_attribute(attr_def)
|
60
|
+
self.class.attribute_class.new(attr_def).call
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module LDAP
|
5
|
+
class Directory
|
6
|
+
|
7
|
+
# https://ldapwiki.com/wiki/Lightweight%20Directory%20Access%20Protocol%20%28LDAP%29%20Transactions
|
8
|
+
# https://tools.ietf.org/html/rfc5805
|
9
|
+
# https://ldapwiki.com/wiki/EDirectory%20LDAP%20Transaction
|
10
|
+
#
|
11
|
+
module Transactions
|
12
|
+
# @example
|
13
|
+
# directory.transaction(opts) { yield(self) }
|
14
|
+
#
|
15
|
+
# @todo Transactions WIP
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
def transaction(_opts)
|
19
|
+
# binding.pry
|
20
|
+
|
21
|
+
# OID[:transaction_start_request]
|
22
|
+
# OID[:transaction_spec_request]
|
23
|
+
# OID[:transaction_end_request]
|
24
|
+
|
25
|
+
yield()
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module LDAP
|
5
|
+
#
|
6
|
+
# Microsoft Active Directory Extension
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
module ActiveDirectory
|
10
|
+
#
|
11
|
+
# @note
|
12
|
+
# Use the AD Forest configuration container as a search base.
|
13
|
+
#
|
14
|
+
# @see https://msdn.microsoft.com/en-us/library/ms684291(v=vs.85).aspx
|
15
|
+
#
|
16
|
+
# RootDSE domainFunctionality
|
17
|
+
# RootDSE domainControllerFunctionality
|
18
|
+
# RootDSE forestFunctionality
|
19
|
+
#
|
20
|
+
VERSION_NAMES = {
|
21
|
+
0 => 'Windows Server 2000 (5.0)',
|
22
|
+
1 => 'Windows Server 2003 (5.2)',
|
23
|
+
2 => 'Windows Server 2003 R2 (5.2)',
|
24
|
+
3 => 'Windows Server 2008 (6.0)',
|
25
|
+
4 => 'Windows Server 2008 R2 (6.1)',
|
26
|
+
5 => 'Windows Server 2012 (6.2)',
|
27
|
+
6 => 'Windows Server 2012 R2 (6.3)',
|
28
|
+
7 => 'Windows Server 2016 (10.0)',
|
29
|
+
8 => 'Windows Server Latest Version (?)'
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
#
|
33
|
+
# RootDSE supportedLDAPPolicies
|
34
|
+
#
|
35
|
+
POLICIES = %w[
|
36
|
+
InitRecvTimeout
|
37
|
+
MaxBatchReturnMessages
|
38
|
+
MaxConnections
|
39
|
+
MaxConnIdleTime
|
40
|
+
MaxDatagramRecv
|
41
|
+
MaxNotificationPerConn
|
42
|
+
MaxPageSize
|
43
|
+
MaxPercentDirSyncRequests
|
44
|
+
MaxPoolThreads
|
45
|
+
MaxQueryDuration
|
46
|
+
MaxReceiveBuffer
|
47
|
+
MaxResultSetSize
|
48
|
+
MaxResultSetsPerConn
|
49
|
+
MaxTempTableSize
|
50
|
+
MaxValRange
|
51
|
+
MaxValRangeTransitive
|
52
|
+
MinResultSets
|
53
|
+
SystemMemoryLimitPercent
|
54
|
+
ThreadMemoryLimit
|
55
|
+
].freeze
|
56
|
+
|
57
|
+
# @return [String]
|
58
|
+
#
|
59
|
+
def vendor_name
|
60
|
+
'Microsoft'
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String]
|
64
|
+
#
|
65
|
+
def vendor_version
|
66
|
+
VERSION_NAMES[domain_functionality]
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Integer]
|
70
|
+
#
|
71
|
+
def controller_functionality
|
72
|
+
root.first('domainControllerFunctionality').to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Integer]
|
76
|
+
#
|
77
|
+
def forest_functionality
|
78
|
+
root.first('forestFunctionality').to_i
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Integer]
|
82
|
+
#
|
83
|
+
def domain_functionality
|
84
|
+
root.first('domainFunctionality').to_i
|
85
|
+
end
|
86
|
+
|
87
|
+
# LDAP server internal clock
|
88
|
+
#
|
89
|
+
# @return [Time]
|
90
|
+
#
|
91
|
+
def directory_time
|
92
|
+
Functions[:to_time][root.first('currentTime')]
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Array<String>]
|
96
|
+
#
|
97
|
+
def supported_capabilities
|
98
|
+
root['supportedCapabilities'].sort
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# OID = OID.dup.merge!(
|
103
|
+
# extended_dn: '1.2.840.113556.1.4.529', # Extended DN control (Stateless)
|
104
|
+
# get_stats: '1.2.840.113556.1.4.970', # Get stats control (Stateless)
|
105
|
+
# verify_name: '1.2.840.113556.1.4.1338', # Verify name control (Stateless)
|
106
|
+
# domain_scope: '1.2.840.113556.1.4.1339', # LDAP_SERVER_DOMAIN_SCOPE_OID
|
107
|
+
# unknown: '1.2.840.113556.1.4.1340',
|
108
|
+
# # unknown: '1.2.840.113556.1.4.1341',
|
109
|
+
# # unknown: '1.2.840.113556.1.4.1413',
|
110
|
+
# # unknown: '1.2.840.113556.1.4.1504',
|
111
|
+
# # unknown: '1.2.840.113556.1.4.1852',
|
112
|
+
# # unknown: '1.2.840.113556.1.4.1907',
|
113
|
+
# # unknown: '1.2.840.113556.1.4.1948',
|
114
|
+
# # unknown: '1.2.840.113556.1.4.1974',
|
115
|
+
# # unknown: '1.2.840.113556.1.4.2026',
|
116
|
+
# # unknown: '1.2.840.113556.1.4.2064',
|
117
|
+
# # unknown: '1.2.840.113556.1.4.2065',
|
118
|
+
# # unknown: '1.2.840.113556.1.4.2066',
|
119
|
+
# # unknown: '1.2.840.113556.1.4.2090',
|
120
|
+
# # unknown: '1.2.840.113556.1.4.2204',
|
121
|
+
# # unknown: '1.2.840.113556.1.4.2205',
|
122
|
+
# # unknown: '1.2.840.113556.1.4.2206',
|
123
|
+
# # unknown: '1.2.840.113556.1.4.2211',
|
124
|
+
# # unknown: '1.2.840.113556.1.4.2239',
|
125
|
+
# # unknown: '1.2.840.113556.1.4.2255',
|
126
|
+
# # unknown: '1.2.840.113556.1.4.2256'
|
127
|
+
# ).freeze
|
128
|
+
end
|
129
|
+
end
|