fakeldap 0.0.1 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +7 -1
- data/lib/fakeldap.rb +133 -10
- data/lib/fakeldap/version.rb +1 -1
- metadata +50 -191
- data/vendor/ruby-ldapserver/COPYING +0 -27
- data/vendor/ruby-ldapserver/ChangeLog +0 -83
- data/vendor/ruby-ldapserver/Manifest.txt +0 -32
- data/vendor/ruby-ldapserver/README +0 -222
- data/vendor/ruby-ldapserver/Rakefile +0 -22
- data/vendor/ruby-ldapserver/doc/LDAP.html +0 -104
- data/vendor/ruby-ldapserver/doc/LDAP/Abandon.html +0 -112
- data/vendor/ruby-ldapserver/doc/LDAP/Error.html +0 -115
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError.html +0 -241
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AdminLimitExceeded.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AffectsMultipleDSAs.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AliasDereferencingProblem.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AliasProblem.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AttributeOrValueExists.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AuthMethodNotSupported.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Busy.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/CompareFalse.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/CompareTrue.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ConfidentialityRequired.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ConstraintViolation.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/EntryAlreadyExists.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InappropriateAuthentication.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InappropriateMatching.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InsufficientAccessRights.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidAttributeSyntax.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidCredentials.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidDNSyntax.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/IsLeaf.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/LoopDetect.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NamingViolation.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NoSuchAttribute.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NoSuchObject.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NotAllowedOnNonLeaf.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NotAllowedOnRDN.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ObjectClassModsProhibited.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ObjectClassViolation.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/OperationsError.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Other.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ProtocolError.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Referral.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/SaslBindInProgress.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/SizeLimitExceeded.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/StrongAuthRequired.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Success.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/TimeLimitExceeded.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Unavailable.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UnavailableCriticalExtension.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UndefinedAttributeType.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UnwillingToPerform.html +0 -158
- data/vendor/ruby-ldapserver/doc/LDAP/Server.html +0 -1056
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Connection.html +0 -1353
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Filter.html +0 -634
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule.html +0 -1132
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/DefaultMatchingClass.html +0 -219
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Equality.html +0 -170
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/IA5Downcase.html +0 -143
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/IA5Trim.html +0 -155
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Integer.html +0 -143
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Ordering.html +0 -212
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/StringDowncase.html +0 -143
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/StringTrim.html +0 -154
- data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Substrings.html +0 -177
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Operation.html +0 -2994
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema.html +0 -2024
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema/AttributeType.html +0 -1462
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema/ObjectClass.html +0 -1097
- data/vendor/ruby-ldapserver/doc/LDAP/Server/Syntax.html +0 -1254
- data/vendor/ruby-ldapserver/doc/LDAP/Server/VERSION.html +0 -134
- data/vendor/ruby-ldapserver/doc/_index.html +0 -662
- data/vendor/ruby-ldapserver/doc/class_list.html +0 -36
- data/vendor/ruby-ldapserver/doc/css/common.css +0 -1
- data/vendor/ruby-ldapserver/doc/css/full_list.css +0 -50
- data/vendor/ruby-ldapserver/doc/css/style.css +0 -303
- data/vendor/ruby-ldapserver/doc/file.README.html +0 -399
- data/vendor/ruby-ldapserver/doc/file_list.html +0 -38
- data/vendor/ruby-ldapserver/doc/frames.html +0 -13
- data/vendor/ruby-ldapserver/doc/index.html +0 -399
- data/vendor/ruby-ldapserver/doc/js/app.js +0 -204
- data/vendor/ruby-ldapserver/doc/js/full_list.js +0 -112
- data/vendor/ruby-ldapserver/doc/js/jquery.js +0 -154
- data/vendor/ruby-ldapserver/doc/method_list.html +0 -1571
- data/vendor/ruby-ldapserver/doc/top-level-namespace.html +0 -88
- data/vendor/ruby-ldapserver/examples/README +0 -89
- data/vendor/ruby-ldapserver/examples/mkcert.rb +0 -31
- data/vendor/ruby-ldapserver/examples/rbslapd1.rb +0 -111
- data/vendor/ruby-ldapserver/examples/rbslapd2.rb +0 -161
- data/vendor/ruby-ldapserver/examples/rbslapd3.rb +0 -172
- data/vendor/ruby-ldapserver/examples/speedtest.rb +0 -37
- data/vendor/ruby-ldapserver/lib/ldap/server.rb +0 -4
- data/vendor/ruby-ldapserver/lib/ldap/server/connection.rb +0 -276
- data/vendor/ruby-ldapserver/lib/ldap/server/filter.rb +0 -223
- data/vendor/ruby-ldapserver/lib/ldap/server/match.rb +0 -283
- data/vendor/ruby-ldapserver/lib/ldap/server/operation.rb +0 -487
- data/vendor/ruby-ldapserver/lib/ldap/server/preforkserver.rb +0 -93
- data/vendor/ruby-ldapserver/lib/ldap/server/result.rb +0 -71
- data/vendor/ruby-ldapserver/lib/ldap/server/schema.rb +0 -592
- data/vendor/ruby-ldapserver/lib/ldap/server/server.rb +0 -89
- data/vendor/ruby-ldapserver/lib/ldap/server/syntax.rb +0 -235
- data/vendor/ruby-ldapserver/lib/ldap/server/tcpserver.rb +0 -91
- data/vendor/ruby-ldapserver/lib/ldap/server/util.rb +0 -88
- data/vendor/ruby-ldapserver/lib/ldap/server/version.rb +0 -11
- data/vendor/ruby-ldapserver/test/core.schema +0 -582
- data/vendor/ruby-ldapserver/test/encoding_test.rb +0 -279
- data/vendor/ruby-ldapserver/test/filter_test.rb +0 -107
- data/vendor/ruby-ldapserver/test/match_test.rb +0 -59
- data/vendor/ruby-ldapserver/test/schema_test.rb +0 -113
- data/vendor/ruby-ldapserver/test/syntax_test.rb +0 -40
- data/vendor/ruby-ldapserver/test/test_helper.rb +0 -2
- data/vendor/ruby-ldapserver/test/util_test.rb +0 -51
@@ -1,223 +0,0 @@
|
|
1
|
-
require 'ldap/server/result'
|
2
|
-
require 'ldap/server/match'
|
3
|
-
|
4
|
-
module LDAP
|
5
|
-
class Server
|
6
|
-
|
7
|
-
# LDAP filters are parsed into a LISP-like internal representation:
|
8
|
-
#
|
9
|
-
# [:true]
|
10
|
-
# [:false]
|
11
|
-
# [:undef]
|
12
|
-
# [:and, ..., ..., ...]
|
13
|
-
# [:or, ..., ..., ...]
|
14
|
-
# [:not, ...]
|
15
|
-
# [:present, attr]
|
16
|
-
# [:eq, attr, MO, val]
|
17
|
-
# [:approx, attr, MO, val]
|
18
|
-
# [:substrings, attr, MO, initial=nil, {any, any...}, final=nil]
|
19
|
-
# [:ge, attr, MO, val]
|
20
|
-
# [:le, attr, MO, val]
|
21
|
-
#
|
22
|
-
# This is done rather than a more object-oriented approach, in the
|
23
|
-
# hope that it will make it easier to match certain filter structures
|
24
|
-
# when converting them into something else. e.g. certain LDAP filter
|
25
|
-
# constructs can be mapped to some fixed SQL queries.
|
26
|
-
#
|
27
|
-
# See RFC 2251 4.5.1 for the three-state(!) boolean logic from LDAP
|
28
|
-
#
|
29
|
-
# If no schema is provided: 'attr' is the raw attribute name as provided
|
30
|
-
# by the client. If a schema is provided: attr is converted to its
|
31
|
-
# normalized name as listed in the schema, e.g. 'commonname' becomes 'cn',
|
32
|
-
# 'objectclass' becomes 'objectClass' etc.
|
33
|
-
# If a schema is provided, MO is a matching object which can be used to
|
34
|
-
# perform the match. If no schema is provided, this is 'nil'. In that
|
35
|
-
# case you could use LDAP::Server::MatchingRule::DefaultMatch.
|
36
|
-
|
37
|
-
class Filter
|
38
|
-
|
39
|
-
# Parse a filter in OpenSSL::ASN1 format into our own format.
|
40
|
-
#
|
41
|
-
# There are some trivial optimisations we make: e.g.
|
42
|
-
# (&(objectClass=*)(cn=foo)) -> (&(cn=foo)) -> (cn=foo)
|
43
|
-
|
44
|
-
def self.parse(asn1, schema=nil)
|
45
|
-
case asn1.tag
|
46
|
-
when 0 # and
|
47
|
-
conds = asn1.value.collect { |a| parse(a) }
|
48
|
-
conds.delete([:true])
|
49
|
-
return [:true] if conds.size == 0
|
50
|
-
return conds.first if conds.size == 1
|
51
|
-
return [:false] if conds.include?([:false])
|
52
|
-
return conds.unshift(:and)
|
53
|
-
|
54
|
-
when 1 # or
|
55
|
-
conds = asn1.value.collect { |a| parse(a) }
|
56
|
-
conds.delete([:false])
|
57
|
-
return [:false] if conds.size == 0
|
58
|
-
return conds.first if conds.size == 1
|
59
|
-
return [:true] if conds.include?([:true])
|
60
|
-
return conds.unshift(:or)
|
61
|
-
|
62
|
-
when 2 # not
|
63
|
-
cond = parse(asn1.value[0])
|
64
|
-
case cond
|
65
|
-
when [:false]; return [:true]
|
66
|
-
when [:true]; return [:false]
|
67
|
-
when [:undef]; return [:undef]
|
68
|
-
end
|
69
|
-
return [:not, cond]
|
70
|
-
|
71
|
-
when 3 # equalityMatch
|
72
|
-
attr = asn1.value[0].value
|
73
|
-
val = asn1.value[1].value
|
74
|
-
return [:true] if attr =~ /\AobjectClass\z/i and val =~ /\Atop\z/i
|
75
|
-
if schema
|
76
|
-
a = schema.find_attrtype(attr)
|
77
|
-
return [:undef] unless a.equality
|
78
|
-
return [:eq, a.to_s, a.equality, val]
|
79
|
-
end
|
80
|
-
return [:eq, attr, nil, val]
|
81
|
-
|
82
|
-
when 4 # substrings
|
83
|
-
attr = asn1.value[0].value
|
84
|
-
if schema
|
85
|
-
a = schema.find_attrtype(attr)
|
86
|
-
return [:undef] unless a.substr
|
87
|
-
res = [:substrings, a.to_s, a.substr, nil]
|
88
|
-
else
|
89
|
-
res = [:substrings, attr, nil, nil]
|
90
|
-
end
|
91
|
-
final_val = nil
|
92
|
-
|
93
|
-
asn1.value[1].value.each do |ss|
|
94
|
-
case ss.tag
|
95
|
-
when 0
|
96
|
-
res[3] = ss.value
|
97
|
-
when 1
|
98
|
-
res << ss.value
|
99
|
-
when 2
|
100
|
-
final_val = ss.value
|
101
|
-
else
|
102
|
-
raise LDAP::ResultError::ProtocolError,
|
103
|
-
"Unrecognised substring tag #{ss.tag.inspect}"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
res << final_val
|
107
|
-
return res
|
108
|
-
|
109
|
-
when 5 # greaterOrEqual
|
110
|
-
attr = asn1.value[0].value
|
111
|
-
val = asn1.value[1].value
|
112
|
-
if schema
|
113
|
-
a = schema.find_attrtype(attr)
|
114
|
-
return [:undef] unless a.ordering
|
115
|
-
return [:ge, a.to_s, a.ordering, val]
|
116
|
-
end
|
117
|
-
return [:ge, attr, nil, val]
|
118
|
-
|
119
|
-
when 6 # lessOrEqual
|
120
|
-
attr = asn1.value[0].value
|
121
|
-
val = asn1.value[1].value
|
122
|
-
if schema
|
123
|
-
a = schema.find_attrtype(attr)
|
124
|
-
return [:undef] unless a.ordering
|
125
|
-
return [:le, a.to_s, a.ordering, val]
|
126
|
-
end
|
127
|
-
return [:le, attr, nil, val]
|
128
|
-
|
129
|
-
when 7 # present
|
130
|
-
attr = asn1.value
|
131
|
-
return [:true] if attr =~ /\AobjectClass\z/i
|
132
|
-
if schema
|
133
|
-
begin
|
134
|
-
a = schema.find_attrtype(attr)
|
135
|
-
return [:present, a.to_s]
|
136
|
-
rescue LDAP::ResultError::UndefinedAttributeType
|
137
|
-
return [:false]
|
138
|
-
end
|
139
|
-
end
|
140
|
-
return [:present, attr]
|
141
|
-
|
142
|
-
when 8 # approxMatch
|
143
|
-
attr = asn1.value[0].value
|
144
|
-
val = asn1.value[1].value
|
145
|
-
if schema
|
146
|
-
a = schema.find_attrtype(attr)
|
147
|
-
# I don't know how properly to deal with approxMatch. I'm assuming
|
148
|
-
# that the object will have an equality MatchingRule, and we
|
149
|
-
# can defer to that.
|
150
|
-
return [:undef] unless a.equality
|
151
|
-
return [:approx, a.to_s, a.equality, val]
|
152
|
-
end
|
153
|
-
return [:approx, attr, nil, val]
|
154
|
-
|
155
|
-
#when 9 # extensibleMatch
|
156
|
-
# FIXME
|
157
|
-
|
158
|
-
else
|
159
|
-
raise LDAP::ResultError::ProtocolError,
|
160
|
-
"Unrecognised Filter tag #{asn1.tag}"
|
161
|
-
end
|
162
|
-
|
163
|
-
# Unknown attribute type
|
164
|
-
rescue LDAP::ResultError::UndefinedAttributeType
|
165
|
-
return [:undef]
|
166
|
-
end
|
167
|
-
|
168
|
-
# Run a parsed filter against an attr=>[val] hash.
|
169
|
-
#
|
170
|
-
# Returns true, false or nil.
|
171
|
-
|
172
|
-
def self.run(filter, av)
|
173
|
-
case filter[0]
|
174
|
-
when :and
|
175
|
-
res = true
|
176
|
-
filter[1..-1].each do |elem|
|
177
|
-
r = run(elem, av)
|
178
|
-
return false if r == false
|
179
|
-
res = nil if r.nil?
|
180
|
-
end
|
181
|
-
return res
|
182
|
-
|
183
|
-
when :or
|
184
|
-
res = false
|
185
|
-
filter[1..-1].each do |elem|
|
186
|
-
r = run(elem, av)
|
187
|
-
return true if r == true
|
188
|
-
res = nil if r.nil?
|
189
|
-
end
|
190
|
-
return res
|
191
|
-
|
192
|
-
when :not
|
193
|
-
case run(filter[1], av)
|
194
|
-
when true; return false
|
195
|
-
when false; return true
|
196
|
-
else return nil
|
197
|
-
end
|
198
|
-
|
199
|
-
when :present
|
200
|
-
return av.has_key?(filter[1])
|
201
|
-
|
202
|
-
when :eq, :approx, :le, :ge, :substrings
|
203
|
-
# the filter now includes a suitable matching object
|
204
|
-
return (filter[2] || LDAP::Server::MatchingRule::DefaultMatch).send(
|
205
|
-
filter.first, av[filter[1].to_s], *filter[3..-1])
|
206
|
-
|
207
|
-
when :true
|
208
|
-
return true
|
209
|
-
|
210
|
-
when :false
|
211
|
-
return false
|
212
|
-
|
213
|
-
when :undef
|
214
|
-
return nil
|
215
|
-
end
|
216
|
-
|
217
|
-
raise LDAP::ResultError::OperationsError,
|
218
|
-
"Unimplemented filter #{filter.first.inspect}"
|
219
|
-
end
|
220
|
-
|
221
|
-
end # class Filter
|
222
|
-
end # class Server
|
223
|
-
end # module LDAP
|
@@ -1,283 +0,0 @@
|
|
1
|
-
require 'ldap/server/syntax'
|
2
|
-
require 'ldap/server/result'
|
3
|
-
|
4
|
-
module LDAP
|
5
|
-
class Server
|
6
|
-
|
7
|
-
# A class which holds LDAP MatchingRules. For now there is a global pool
|
8
|
-
# of MatchingRule objects (rather than each Schema object having
|
9
|
-
# its own pool)
|
10
|
-
|
11
|
-
class MatchingRule
|
12
|
-
attr_reader :oid, :names, :syntax, :desc, :obsolete
|
13
|
-
|
14
|
-
# Create a new MatchingRule object
|
15
|
-
|
16
|
-
def initialize(oid, names, syntax, desc=nil, obsolete=false, &blk)
|
17
|
-
@oid = oid
|
18
|
-
@names = names
|
19
|
-
@names = [@names] unless @names.is_a?(Array)
|
20
|
-
@desc = desc
|
21
|
-
@obsolete = obsolete
|
22
|
-
@syntax = LDAP::Server::Syntax.find(syntax) # creates new obj if reqd
|
23
|
-
@def = nil
|
24
|
-
# initialization hook
|
25
|
-
self.instance_eval(&blk) if blk
|
26
|
-
end
|
27
|
-
|
28
|
-
def name
|
29
|
-
(@names && names[0]) || @oid
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
(@names && names[0]) || @oid
|
34
|
-
end
|
35
|
-
|
36
|
-
def normalize(x)
|
37
|
-
x
|
38
|
-
end
|
39
|
-
|
40
|
-
# Create a new MatchingRule object, given its description string
|
41
|
-
|
42
|
-
def self.from_def(str, &blk)
|
43
|
-
m = LDAP::Server::Syntax::MatchingRuleDescription.match(str)
|
44
|
-
raise LDAP::ResultError::InvalidAttributeSyntax,
|
45
|
-
"Bad MatchingRuleDescription #{str.inspect}" unless m
|
46
|
-
new(m[1], m[2].scan(/'(.*?)'/).flatten, m[5], m[3], m[4], &blk)
|
47
|
-
end
|
48
|
-
|
49
|
-
def to_def
|
50
|
-
return @def if @def
|
51
|
-
ans = "( #{@oid} "
|
52
|
-
if names.nil? or @names.empty?
|
53
|
-
# nothing
|
54
|
-
elsif @names.size == 1
|
55
|
-
ans << "NAME '#{@names[0]}' "
|
56
|
-
else
|
57
|
-
ans << "NAME ( "
|
58
|
-
@names.each { |n| ans << "'#{n}' " }
|
59
|
-
ans << ") "
|
60
|
-
end
|
61
|
-
ans << "DESC '#@desc' " if @desc
|
62
|
-
ans << "OBSOLETE " if @obsolete
|
63
|
-
ans << "SYNTAX #@syntax " if @syntax
|
64
|
-
ans << ")"
|
65
|
-
@def = ans
|
66
|
-
end
|
67
|
-
|
68
|
-
@@rules = {} # oid / name / alias => object
|
69
|
-
|
70
|
-
# Add a new matching rule
|
71
|
-
|
72
|
-
def self.add(*args, &blk)
|
73
|
-
s = new(*args, &blk)
|
74
|
-
@@rules[s.oid] = s
|
75
|
-
return if s.names.nil?
|
76
|
-
s.names.each do |n|
|
77
|
-
@@rules[n.downcase] = s
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Find a MatchingRule object given a name or oid, or return nil
|
82
|
-
# (? should we create one automatically, like Syntax)
|
83
|
-
|
84
|
-
def self.find(x)
|
85
|
-
return x if x.nil? or x.is_a?(LDAP::Server::MatchingRule)
|
86
|
-
@@rules[x.downcase]
|
87
|
-
end
|
88
|
-
|
89
|
-
# Return all known matching rules
|
90
|
-
|
91
|
-
def self.all_matching_rules
|
92
|
-
@@rules.values.uniq
|
93
|
-
end
|
94
|
-
|
95
|
-
# Now some things we can mixin to a MatchingRule when needed.
|
96
|
-
# Replace 'normalize' with a function which gives the canonical
|
97
|
-
# version of a value for comparison.
|
98
|
-
|
99
|
-
module Equality
|
100
|
-
def eq(vals, m)
|
101
|
-
return false if vals.nil?
|
102
|
-
m = normalize(m)
|
103
|
-
vals.each { |v| return true if normalize(v) == m }
|
104
|
-
return false
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
module Ordering
|
109
|
-
def ge(vals, m)
|
110
|
-
return false if vals.nil?
|
111
|
-
m = normalize(m)
|
112
|
-
vals.each { |v| return true if normalize(v) >= m }
|
113
|
-
return false
|
114
|
-
end
|
115
|
-
|
116
|
-
def le(vals, m)
|
117
|
-
return false if vals.nil?
|
118
|
-
m = normalize(m)
|
119
|
-
vals.each { |v| return true if normalize(v) <= m }
|
120
|
-
return false
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
module Substrings
|
125
|
-
def substrings(vals, *ss)
|
126
|
-
return false if vals.nil?
|
127
|
-
|
128
|
-
# convert the condition list into a regexp
|
129
|
-
re = []
|
130
|
-
re << "^#{Regexp.escape(normalize(ss[0]).to_s)}" if ss[0]
|
131
|
-
ss[1..-2].each { |s| re << Regexp.escape(normalize(s).to_s) }
|
132
|
-
re << "#{Regexp.escape(normalize(ss[-1]).to_s)}$" if ss[-1]
|
133
|
-
re = Regexp.new(re.join(".*"))
|
134
|
-
|
135
|
-
vals.each do |v|
|
136
|
-
v = normalize(v).to_s
|
137
|
-
return true if re.match(v)
|
138
|
-
end
|
139
|
-
return false
|
140
|
-
end
|
141
|
-
end # module Substrings
|
142
|
-
|
143
|
-
class DefaultMatchingClass
|
144
|
-
include MatchingRule::Equality
|
145
|
-
include MatchingRule::Ordering
|
146
|
-
include MatchingRule::Substrings
|
147
|
-
def normalize(x)
|
148
|
-
x
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
DefaultMatch = DefaultMatchingClass.new
|
153
|
-
|
154
|
-
end # class MatchingRule
|
155
|
-
|
156
|
-
#
|
157
|
-
# And now, here are some matching rules you can use (RFC2252 section 8)
|
158
|
-
#
|
159
|
-
|
160
|
-
class MatchingRule
|
161
|
-
|
162
|
-
add('2.5.13.0', 'objectIdentifierMatch', '1.3.6.1.4.1.1466.115.121.1.38') do
|
163
|
-
extend Equality
|
164
|
-
end
|
165
|
-
# FIXME: Filters should return undef if the OID is not in the schema
|
166
|
-
# (which means passing in the schema to every equality test)
|
167
|
-
|
168
|
-
add('2.5.13.1', 'distinguishedNameMatch', '1.3.6.1.4.1.1466.115.121.1.12') do
|
169
|
-
extend Equality
|
170
|
-
end
|
171
|
-
# FIXME: Distinguished Name matching is supposed to parse the DN into
|
172
|
-
# its parts and then apply the schema equality rules to each part
|
173
|
-
# (i.e. some parts may be case-sensitive, others case-insensitive)
|
174
|
-
# This is just one of the many nonsense design decisions in LDAP :-(
|
175
|
-
|
176
|
-
# How is a DirectoryString different to an IA5String or a PrintableString?
|
177
|
-
|
178
|
-
module StringTrim
|
179
|
-
def normalize(x); x.gsub(/^\s*|\s*$/, '').gsub(/\s+/,' '); end
|
180
|
-
end
|
181
|
-
|
182
|
-
module StringDowncase
|
183
|
-
def normalize(x); x.downcase.gsub(/^\s*|\s*$/, '').gsub(/\s+/,' '); end
|
184
|
-
end
|
185
|
-
|
186
|
-
add('2.5.13.2', 'caseIgnoreMatch', '1.3.6.1.4.1.1466.115.1') do
|
187
|
-
extend Equality
|
188
|
-
extend StringDowncase
|
189
|
-
end
|
190
|
-
|
191
|
-
module Integer
|
192
|
-
def normalize(x); x.to_i; end
|
193
|
-
end
|
194
|
-
|
195
|
-
add('2.5.13.8', 'numericStringMatch', '1.3.6.1.4.1.1466.115.121.1.36') do
|
196
|
-
extend Equality
|
197
|
-
extend Integer
|
198
|
-
end
|
199
|
-
|
200
|
-
# TODO: Add semantics for these (difficult since RFC2252 doesn't give
|
201
|
-
# them, so we presumably have to go through X.500)
|
202
|
-
add('2.5.13.11', 'caseIgnoreListMatch', '1.3.6.1.4.1.1466.115.121.1.41')
|
203
|
-
add('2.5.13.14', 'integerMatch', '1.3.6.1.4.1.1466.115.121.1.27') do
|
204
|
-
extend Equality
|
205
|
-
extend Integer
|
206
|
-
end
|
207
|
-
add('2.5.13.16', 'bitStringMatch', '1.3.6.1.4.1.1466.115.121.1.6')
|
208
|
-
add('2.5.13.20', 'telephoneNumberMatch', '1.3.6.1.4.1.1466.115.121.1.50') do
|
209
|
-
extend Equality
|
210
|
-
extend StringTrim
|
211
|
-
end
|
212
|
-
add('2.5.13.22', 'presentationAddressMatch', '1.3.6.1.4.1.1466.115.121.1.43')
|
213
|
-
add('2.5.13.23', 'uniqueMemberMatch', '1.3.6.1.4.1.1466.115.121.1.34')
|
214
|
-
add('2.5.13.24', 'protocolInformationMatch', '1.3.6.1.4.1.1466.115.121.1.42')
|
215
|
-
add('2.5.13.27', 'generalizedTimeMatch', '1.3.6.1.4.1.1466.115.121.1.24') { extend Equality }
|
216
|
-
|
217
|
-
# IA5 stuff. FIXME: What's the correct way to 'downcase' UTF8 strings?
|
218
|
-
|
219
|
-
module IA5Trim
|
220
|
-
def normalize(x); x.gsub(/^\s*|\s*$/u, '').gsub(/\s+/u,' '); end
|
221
|
-
end
|
222
|
-
|
223
|
-
module IA5Downcase
|
224
|
-
def normalize(x); x.downcase.gsub(/^\s*|\s*$/u, '').gsub(/\s+/u,' '); end
|
225
|
-
end
|
226
|
-
|
227
|
-
add('1.3.6.1.4.1.1466.109.114.1', 'caseExactIA5Match', '1.3.6.1.4.1.1466.115.121.1.26') do
|
228
|
-
extend Equality
|
229
|
-
extend IA5Trim
|
230
|
-
end
|
231
|
-
|
232
|
-
add('1.3.6.1.4.1.1466.109.114.2', 'caseIgnoreIA5Match', '1.3.6.1.4.1.1466.115.121.1.26') do
|
233
|
-
extend Equality
|
234
|
-
extend IA5Downcase
|
235
|
-
end
|
236
|
-
|
237
|
-
add('2.5.13.28', 'generalizedTimeOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.24') { extend Ordering }
|
238
|
-
add('2.5.13.3', 'caseIgnoreOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.15') do
|
239
|
-
extend Ordering
|
240
|
-
extend StringDowncase
|
241
|
-
end
|
242
|
-
|
243
|
-
add('2.5.13.4', 'caseIgnoreSubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.58') do
|
244
|
-
extend Substrings
|
245
|
-
extend StringDowncase
|
246
|
-
end
|
247
|
-
add('2.5.13.21', 'telephoneNumberSubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.58') do
|
248
|
-
extend Substrings
|
249
|
-
end
|
250
|
-
add('2.5.13.10', 'numericStringSubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.58') do
|
251
|
-
extend Substrings
|
252
|
-
end
|
253
|
-
|
254
|
-
# from OpenLDAP
|
255
|
-
add('1.3.6.1.4.1.4203.1.2.1', 'caseExactIA5SubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.26') do
|
256
|
-
extend Substrings
|
257
|
-
extend IA5Trim
|
258
|
-
end
|
259
|
-
add('1.3.6.1.4.1.1466.109.114.3', 'caseIgnoreIA5SubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.26') do
|
260
|
-
extend Substrings
|
261
|
-
extend IA5Downcase
|
262
|
-
end
|
263
|
-
add('2.5.13.5', 'caseExactMatch', '1.3.6.1.4.1.1466.115.121.1.15') { extend Equality }
|
264
|
-
add('2.5.13.6', 'caseExactOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.15') { extend Ordering }
|
265
|
-
add('2.5.13.7', 'caseExactSubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.58') { extend Substrings }
|
266
|
-
add('2.5.13.9', 'numericStringOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.36') { extend Ordering; extend Integer }
|
267
|
-
add('2.5.13.13', 'booleanMatch', '1.3.6.1.4.1.1466.115.121.1.7') do
|
268
|
-
extend Equality
|
269
|
-
def self.normalize(x)
|
270
|
-
return true if x == 'TRUE'
|
271
|
-
return false if x == 'FALSE'
|
272
|
-
x
|
273
|
-
end
|
274
|
-
end
|
275
|
-
add('2.5.13.15', 'integerOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.27') { extend Ordering; extend Integer }
|
276
|
-
add('2.5.13.17', 'octetStringMatch', '1.3.6.1.4.1.1466.115.121.1.40') { extend Equality }
|
277
|
-
add('2.5.13.18', 'octetStringOrderingMatch', '1.3.6.1.4.1.1466.115.121.1.40') { extend Ordering }
|
278
|
-
add('2.5.13.19', 'octetStringSubstringsMatch', '1.3.6.1.4.1.1466.115.121.1.40') { extend Substrings }
|
279
|
-
|
280
|
-
end # class MatchingRule
|
281
|
-
|
282
|
-
end # class Server
|
283
|
-
end # module LDAP
|