fakeldap 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +7 -1
  3. data/lib/fakeldap.rb +133 -10
  4. data/lib/fakeldap/version.rb +1 -1
  5. metadata +50 -191
  6. data/vendor/ruby-ldapserver/COPYING +0 -27
  7. data/vendor/ruby-ldapserver/ChangeLog +0 -83
  8. data/vendor/ruby-ldapserver/Manifest.txt +0 -32
  9. data/vendor/ruby-ldapserver/README +0 -222
  10. data/vendor/ruby-ldapserver/Rakefile +0 -22
  11. data/vendor/ruby-ldapserver/doc/LDAP.html +0 -104
  12. data/vendor/ruby-ldapserver/doc/LDAP/Abandon.html +0 -112
  13. data/vendor/ruby-ldapserver/doc/LDAP/Error.html +0 -115
  14. data/vendor/ruby-ldapserver/doc/LDAP/ResultError.html +0 -241
  15. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AdminLimitExceeded.html +0 -158
  16. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AffectsMultipleDSAs.html +0 -158
  17. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AliasDereferencingProblem.html +0 -158
  18. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AliasProblem.html +0 -158
  19. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AttributeOrValueExists.html +0 -158
  20. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/AuthMethodNotSupported.html +0 -158
  21. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Busy.html +0 -158
  22. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/CompareFalse.html +0 -158
  23. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/CompareTrue.html +0 -158
  24. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ConfidentialityRequired.html +0 -158
  25. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ConstraintViolation.html +0 -158
  26. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/EntryAlreadyExists.html +0 -158
  27. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InappropriateAuthentication.html +0 -158
  28. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InappropriateMatching.html +0 -158
  29. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InsufficientAccessRights.html +0 -158
  30. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidAttributeSyntax.html +0 -158
  31. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidCredentials.html +0 -158
  32. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/InvalidDNSyntax.html +0 -158
  33. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/IsLeaf.html +0 -158
  34. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/LoopDetect.html +0 -158
  35. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NamingViolation.html +0 -158
  36. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NoSuchAttribute.html +0 -158
  37. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NoSuchObject.html +0 -158
  38. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NotAllowedOnNonLeaf.html +0 -158
  39. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/NotAllowedOnRDN.html +0 -158
  40. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ObjectClassModsProhibited.html +0 -158
  41. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ObjectClassViolation.html +0 -158
  42. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/OperationsError.html +0 -158
  43. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Other.html +0 -158
  44. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/ProtocolError.html +0 -158
  45. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Referral.html +0 -158
  46. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/SaslBindInProgress.html +0 -158
  47. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/SizeLimitExceeded.html +0 -158
  48. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/StrongAuthRequired.html +0 -158
  49. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Success.html +0 -158
  50. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/TimeLimitExceeded.html +0 -158
  51. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/Unavailable.html +0 -158
  52. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UnavailableCriticalExtension.html +0 -158
  53. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UndefinedAttributeType.html +0 -158
  54. data/vendor/ruby-ldapserver/doc/LDAP/ResultError/UnwillingToPerform.html +0 -158
  55. data/vendor/ruby-ldapserver/doc/LDAP/Server.html +0 -1056
  56. data/vendor/ruby-ldapserver/doc/LDAP/Server/Connection.html +0 -1353
  57. data/vendor/ruby-ldapserver/doc/LDAP/Server/Filter.html +0 -634
  58. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule.html +0 -1132
  59. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/DefaultMatchingClass.html +0 -219
  60. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Equality.html +0 -170
  61. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/IA5Downcase.html +0 -143
  62. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/IA5Trim.html +0 -155
  63. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Integer.html +0 -143
  64. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Ordering.html +0 -212
  65. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/StringDowncase.html +0 -143
  66. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/StringTrim.html +0 -154
  67. data/vendor/ruby-ldapserver/doc/LDAP/Server/MatchingRule/Substrings.html +0 -177
  68. data/vendor/ruby-ldapserver/doc/LDAP/Server/Operation.html +0 -2994
  69. data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema.html +0 -2024
  70. data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema/AttributeType.html +0 -1462
  71. data/vendor/ruby-ldapserver/doc/LDAP/Server/Schema/ObjectClass.html +0 -1097
  72. data/vendor/ruby-ldapserver/doc/LDAP/Server/Syntax.html +0 -1254
  73. data/vendor/ruby-ldapserver/doc/LDAP/Server/VERSION.html +0 -134
  74. data/vendor/ruby-ldapserver/doc/_index.html +0 -662
  75. data/vendor/ruby-ldapserver/doc/class_list.html +0 -36
  76. data/vendor/ruby-ldapserver/doc/css/common.css +0 -1
  77. data/vendor/ruby-ldapserver/doc/css/full_list.css +0 -50
  78. data/vendor/ruby-ldapserver/doc/css/style.css +0 -303
  79. data/vendor/ruby-ldapserver/doc/file.README.html +0 -399
  80. data/vendor/ruby-ldapserver/doc/file_list.html +0 -38
  81. data/vendor/ruby-ldapserver/doc/frames.html +0 -13
  82. data/vendor/ruby-ldapserver/doc/index.html +0 -399
  83. data/vendor/ruby-ldapserver/doc/js/app.js +0 -204
  84. data/vendor/ruby-ldapserver/doc/js/full_list.js +0 -112
  85. data/vendor/ruby-ldapserver/doc/js/jquery.js +0 -154
  86. data/vendor/ruby-ldapserver/doc/method_list.html +0 -1571
  87. data/vendor/ruby-ldapserver/doc/top-level-namespace.html +0 -88
  88. data/vendor/ruby-ldapserver/examples/README +0 -89
  89. data/vendor/ruby-ldapserver/examples/mkcert.rb +0 -31
  90. data/vendor/ruby-ldapserver/examples/rbslapd1.rb +0 -111
  91. data/vendor/ruby-ldapserver/examples/rbslapd2.rb +0 -161
  92. data/vendor/ruby-ldapserver/examples/rbslapd3.rb +0 -172
  93. data/vendor/ruby-ldapserver/examples/speedtest.rb +0 -37
  94. data/vendor/ruby-ldapserver/lib/ldap/server.rb +0 -4
  95. data/vendor/ruby-ldapserver/lib/ldap/server/connection.rb +0 -276
  96. data/vendor/ruby-ldapserver/lib/ldap/server/filter.rb +0 -223
  97. data/vendor/ruby-ldapserver/lib/ldap/server/match.rb +0 -283
  98. data/vendor/ruby-ldapserver/lib/ldap/server/operation.rb +0 -487
  99. data/vendor/ruby-ldapserver/lib/ldap/server/preforkserver.rb +0 -93
  100. data/vendor/ruby-ldapserver/lib/ldap/server/result.rb +0 -71
  101. data/vendor/ruby-ldapserver/lib/ldap/server/schema.rb +0 -592
  102. data/vendor/ruby-ldapserver/lib/ldap/server/server.rb +0 -89
  103. data/vendor/ruby-ldapserver/lib/ldap/server/syntax.rb +0 -235
  104. data/vendor/ruby-ldapserver/lib/ldap/server/tcpserver.rb +0 -91
  105. data/vendor/ruby-ldapserver/lib/ldap/server/util.rb +0 -88
  106. data/vendor/ruby-ldapserver/lib/ldap/server/version.rb +0 -11
  107. data/vendor/ruby-ldapserver/test/core.schema +0 -582
  108. data/vendor/ruby-ldapserver/test/encoding_test.rb +0 -279
  109. data/vendor/ruby-ldapserver/test/filter_test.rb +0 -107
  110. data/vendor/ruby-ldapserver/test/match_test.rb +0 -59
  111. data/vendor/ruby-ldapserver/test/schema_test.rb +0 -113
  112. data/vendor/ruby-ldapserver/test/syntax_test.rb +0 -40
  113. data/vendor/ruby-ldapserver/test/test_helper.rb +0 -2
  114. data/vendor/ruby-ldapserver/test/util_test.rb +0 -51
@@ -1,93 +0,0 @@
1
- require 'prefork' # <http://raa.ruby-lang.org/project/prefork/>
2
- require 'socket'
3
-
4
- module LDAP
5
- class Server
6
-
7
- # Accept connections on a port, and for each one run the given block
8
- # in one of N pre-forked children. Returns a Thread object for the
9
- # listener.
10
- #
11
- # Options:
12
- # :port=>port number [required]
13
- # :bindaddr=>"IP address"
14
- # :user=>"username" - drop privileges after bind
15
- # :group=>"groupname" - ditto
16
- # :logger=>object - implements << method
17
- # :listen=>number - listen queue depth
18
- # :nodelay=>true - set TCP_NODELAY option
19
- # :min_servers=>N - prefork parameters
20
- # :max_servers=>N
21
- # :max_requests_per_child=>N
22
- # :max_idle=>N - seconds
23
-
24
- def self.preforkserver(opt, &blk)
25
- logger = opt[:logger] || $stderr
26
- server = PreFork.new(opt[:bindaddr] || "0.0.0.0", opt[:port])
27
-
28
- # Drop privileges if requested
29
- if opt[:group] or opt[:user]
30
- require 'etc'
31
- gid = Etc.getgrnam(opt[:group]).gid if opt[:group]
32
- uid = Etc.getpwnam(opt[:user]).uid if opt[:user]
33
- File.chown(uid, gid, server.instance_eval {@lockf})
34
- Process.gid = Process.egid = gid if gid
35
- Process.uid = Process.euid = uid if uid
36
- end
37
-
38
- # Typically the O/S will buffer response data for 100ms before sending.
39
- # If the response is sent as a single write() then there's no need for it.
40
- if opt[:nodelay]
41
- begin
42
- server.sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
43
- rescue Exception
44
- end
45
- end
46
- # set queue size for incoming connections (default is 5)
47
- server.sock.listen(opt[:listen]) if opt[:listen]
48
-
49
- # Set prefork server parameters
50
- server.min_servers = opt[:min_servers] if opt[:min_servers]
51
- server.max_servers = opt[:max_servers] if opt[:max_servers]
52
- server.max_request_per_child = opt[:max_request_per_child] if opt[:max_request_per_child]
53
- server.max_idle = opt[:max_idle] if opt[:max_idle]
54
-
55
- Thread.new do
56
- server.start do |s|
57
- begin
58
- s.instance_eval(&blk)
59
- rescue Interrupt
60
- # This exception can be raised to shut the server down
61
- server.stop
62
- rescue Exception => e
63
- logger << "[#{s.peeraddr[3]}]: #{e}: #{e.backtrace[0]}\n"
64
- ensure
65
- s.close
66
- end
67
- end
68
- end
69
- end
70
-
71
- end # class Server
72
- end # module LDAP
73
-
74
- if __FILE__ == $0
75
- # simple test
76
- puts "Running a test POP3 server on port 1110"
77
- t = LDAP::Server.preforkserver(:port=>1110) do
78
- print "+OK I am a fake POP3 server (pid #{$$})\r\n"
79
- while line = gets
80
- case line
81
- when /^quit/i
82
- break
83
- when /^crash/i
84
- raise Errno::EPERM, "dammit!"
85
- else
86
- print "-ERR I don't understand #{line}"
87
- end
88
- end
89
- print "+OK bye\r\n"
90
- end
91
- #sleep 10; t.raise Interrupt # uncomment to run for fixed time period
92
- t.join
93
- end
@@ -1,71 +0,0 @@
1
- module LDAP
2
-
3
- # compatible with ruby-ldap
4
- class Error < StandardError
5
- end
6
-
7
- class ResultError < Error
8
- end
9
-
10
- # This exception is raised when we need to kill an existing Operation
11
- # thread because of a received abandonRequest or bindRequest
12
- class Abandon < Interrupt
13
- end
14
-
15
- # ResultError constants from RFC 2251 4.1.10; these are all exceptions
16
- # which can be raised
17
-
18
- class ResultError
19
- class Success < self; def to_i; 0; end; end
20
- class OperationsError < self; def to_i; 1; end; end
21
- class ProtocolError < self; def to_i; 2; end; end
22
- class TimeLimitExceeded < self; def to_i; 3; end; end
23
- class SizeLimitExceeded < self; def to_i; 4; end; end
24
- class CompareFalse < self; def to_i; 5; end; end
25
- class CompareTrue < self; def to_i; 6; end; end
26
- class AuthMethodNotSupported < self; def to_i; 7; end; end
27
- class StrongAuthRequired < self; def to_i; 8; end; end
28
- class Referral < self; def to_i; 10; end; end
29
- class AdminLimitExceeded < self; def to_i; 11; end; end
30
- class UnavailableCriticalExtension < self; def to_i; 12; end; end
31
- class ConfidentialityRequired < self; def to_i; 13; end; end
32
- class SaslBindInProgress < self; def to_i; 14; end; end
33
- class NoSuchAttribute < self; def to_i; 16; end; end
34
- class UndefinedAttributeType < self; def to_i; 17; end; end
35
- class InappropriateMatching < self; def to_i; 18; end; end
36
- class ConstraintViolation < self; def to_i; 19; end; end
37
- class AttributeOrValueExists < self; def to_i; 20; end; end
38
- class InvalidAttributeSyntax < self; def to_i; 21; end; end
39
- class NoSuchObject < self; def to_i; 32; end; end
40
- class AliasProblem < self; def to_i; 33; end; end
41
- class InvalidDNSyntax < self; def to_i; 34; end; end
42
- class IsLeaf < self; def to_i; 35; end; end
43
- class AliasDereferencingProblem < self; def to_i; 36; end; end
44
- class InappropriateAuthentication < self; def to_i; 48; end; end
45
- class InvalidCredentials < self; def to_i; 49; end; end
46
- class InsufficientAccessRights < self; def to_i; 50; end; end
47
- class Busy < self; def to_i; 51; end; end
48
- class Unavailable < self; def to_i; 52; end; end
49
- class UnwillingToPerform < self; def to_i; 53; end; end
50
- class LoopDetect < self; def to_i; 54; end; end
51
- class NamingViolation < self; def to_i; 64; end; end
52
- class ObjectClassViolation < self; def to_i; 65; end; end
53
- class NotAllowedOnNonLeaf < self; def to_i; 66; end; end
54
- class NotAllowedOnRDN < self; def to_i; 67; end; end
55
- class EntryAlreadyExists < self; def to_i; 68; end; end
56
- class ObjectClassModsProhibited < self; def to_i; 69; end; end
57
- class AffectsMultipleDSAs < self; def to_i; 71; end; end
58
- class Other < self; def to_i; 80; end; end
59
-
60
- # Reverse lookup: so you can do raise LDAP::ResultError[53]
61
-
62
- N_TO_CLASS = {
63
- 53 => UnwillingToPerform,
64
- # FIXME: please fill in the rest
65
- }
66
- def self.[] (n)
67
- return N_TO_CLASS[n] || self
68
- end
69
- end # class ResultError
70
-
71
- end # module LDAP
@@ -1,592 +0,0 @@
1
- require 'ldap/server/syntax'
2
- require 'ldap/server/result'
3
-
4
- module LDAP
5
- class Server
6
-
7
- # This object represents an LDAP schema: that is, a collection of
8
- # objectclasses and attributetypes. Methods are provided for loading
9
- # the schema (from a string or a disk file), and validating an av-hash
10
- # against it.
11
-
12
- class Schema
13
-
14
- SUBSCHEMA_ENTRY_ATTR = 'cn'
15
- SUBSCHEMA_ENTRY_VALUE = 'Subschema'
16
-
17
- def initialize
18
- @attrtypes = {} # name/alias/oid => AttributeType instance
19
- @objectclasses = {} # name/alias/oid => ObjectClass instance
20
- @subschema_cache = nil
21
- end
22
-
23
- # return the DN of the subschema subentry
24
-
25
- def subschema_dn
26
- "#{SUBSCHEMA_ENTRY_ATTR}=#{SUBSCHEMA_ENTRY_VALUE}"
27
- end
28
-
29
- # Return an av hash object giving the subschema subentry. This is cached, so
30
- # call Schema#changed if it needs to be rebuilt
31
-
32
- def subschema_subentry
33
- @subschema_cache ||= {
34
- 'objectClass' => ['top','subschema','extensibleObject'],
35
- SUBSCHEMA_ENTRY_ATTR => [SUBSCHEMA_ENTRY_VALUE],
36
- 'objectClasses' => all_objectclasses.collect { |s| s.to_def },
37
- 'attributeTypes' => all_attrtypes.collect { |s| s.to_def },
38
- 'ldapSyntaxes' => LDAP::Server::Syntax.all_syntaxes.collect { |s| s.to_def },
39
- #'matchingRules' =>
40
- #'matchingRuleUse' =>
41
- }
42
- end
43
-
44
- # Clear the subschema subentry cache, so the next time someone requests
45
- # it, it will be rebuilt
46
-
47
- def changed
48
- @subschema_cache = nil
49
- end
50
-
51
- # Add an AttributeType to the schema
52
-
53
- def add_attrtype(str)
54
- a = AttributeType.new(str)
55
- @attrtypes[a.oid] = a if a.oid
56
- a.names.each do |n|
57
- @attrtypes[n.downcase] = a
58
- end
59
- end
60
-
61
- # Locate an attributetype object by name/alias/oid (or raise exception)
62
-
63
- def find_attrtype(n)
64
- return n if n.nil? or n.is_a?(LDAP::Server::Schema::AttributeType)
65
- r = @attrtypes[n.downcase]
66
- raise LDAP::ResultError::UndefinedAttributeType, "Unknown AttributeType #{n.inspect}" unless r
67
- r
68
- end
69
-
70
- # Return array of all AttributeType objects in this schema
71
-
72
- def all_attrtypes
73
- @attrtypes.values.uniq
74
- end
75
-
76
- # Add an ObjectClass to the schema
77
-
78
- def add_objectclass(str)
79
- o = ObjectClass.new(str)
80
- @objectclasses[o.oid] = o if o.oid
81
- o.names.each do |n|
82
- @objectclasses[n.downcase] = o
83
- end
84
- end
85
-
86
- # Locate an objectclass object by name/alias/oid (or raise exception)
87
-
88
- def find_objectclass(n)
89
- return n if n.nil? or n.is_a?(LDAP::Server::Schema::ObjectClass)
90
- r = @objectclasses[n.downcase]
91
- raise LDAP::ResultError::ObjectClassViolation, "Unknown ObjectClass #{n.inspect}" unless r
92
- r
93
- end
94
-
95
- # Return array of all ObjectClass objects in this schema
96
-
97
- def all_objectclasses
98
- @objectclasses.values.uniq
99
- end
100
-
101
- # Load an OpenLDAP-format schema from a named file (see notes under 'load')
102
-
103
- def load_file(filename)
104
- File.open(filename) { |f| load(f) }
105
- end
106
-
107
- # Load an OpenLDAP-format schema from a string or IO object (anything
108
- # which responds to 'each_line'). Lines starting 'attributetype'
109
- # or 'objectclass' contain one of those objects. Does not implement
110
- # named objectIdentifier prefixes (used in the dyngroup.schema file
111
- # supplied with openldap, but not documented in RFC2252)
112
- #
113
- # Note: RFC2252 is strict about the order in which the elements appear,
114
- # and so are we, but OpenLDAP is not. This means that a schema which
115
- # works in OpenLDAP might not load here. For example, RFC2252 says
116
- # that in an objectclass description, "SUP" must come before "MAY";
117
- # if they are the other way round, our regexp-based parser will not
118
- # accept it. The solution is simply to modify the definition so that
119
- # the elements appear in the correct order.
120
-
121
- def load(str_or_io)
122
- meth = :junk_line
123
- data = ""
124
- str_or_io.each_line do |line|
125
- case line
126
- when /^\s*#/, /^\s*$/
127
- next
128
- when /^objectclass\s*(.*)$/i
129
- m = $~
130
- send(meth, data)
131
- meth, data = :add_objectclass, m[1]
132
- when /^attributetype\s*(.*)$/i
133
- m = $~
134
- send(meth, data)
135
- meth, data = :add_attrtype, m[1]
136
- else
137
- data << line
138
- end
139
- end
140
- send(meth,data)
141
- self
142
- end
143
-
144
- def junk_line(data)
145
- return if data.empty?
146
- raise LDAP::ResultError::InvalidAttributeSyntax,
147
- "Expected 'attributetype' or 'objectclass', got #{data}"
148
- end
149
- private :junk_line
150
-
151
- # Load in the base set of objectclasses and attributetypes, being
152
- # the same set as OpenLDAP preloads internally. Includes objectclasses
153
- # 'top', 'objectclass'; attributetypes 'objectclass' , 'cn',
154
- # 'userPassword' and 'distinguishedName'; common operational attributes
155
- # such as 'modifyTimestamp'; plus extras needed for publishing a v3
156
- # schema via LDAP
157
-
158
- def load_system
159
- load(<<EOS)
160
- attributetype ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI' DESC 'RFC2079: Uniform Resource Identifier with optional label' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
161
- attributetype ( 2.5.4.35 NAME 'userPassword' DESC 'RFC2256/2307: password of user' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
162
- attributetype ( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by' SUP name )
163
- attributetype ( 2.5.4.41 NAME 'name' DESC 'RFC2256: common supertype of name attributes' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
164
- attributetype ( 2.5.4.49 NAME 'distinguishedName' DESC 'RFC2256: common supertype of DN attributes' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
165
- attributetype ( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'namedref: subordinate referral URL' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE distributedOperation )
166
- attributetype ( 2.5.4.1 NAME ( 'aliasedObjectName' 'aliasedEntryName' ) DESC 'RFC2256: name of aliased object' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
167
- attributetype ( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' DESC 'RFC2252: LDAP syntaxes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )
168
- attributetype ( 2.5.21.8 NAME 'matchingRuleUse' DESC 'RFC2252: matching rule uses' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )
169
- attributetype ( 2.5.21.6 NAME 'objectClasses' DESC 'RFC2252: object classes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )
170
- attributetype ( 2.5.21.5 NAME 'attributeTypes' DESC 'RFC2252: attribute types' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )
171
- attributetype ( 2.5.21.4 NAME 'matchingRules' DESC 'RFC2252: matching rules' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )
172
- attributetype ( 1.3.6.1.1.5 NAME 'vendorVersion' DESC 'RFC3045: version of implementation' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
173
- attributetype ( 1.3.6.1.1.4 NAME 'vendorName' DESC 'RFC3045: name of implementation vendor' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
174
- attributetype ( 1.3.6.1.4.1.4203.1.3.5 NAME 'supportedFeatures' DESC 'features supported by the server' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
175
- attributetype ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms' DESC 'RFC2252: supported SASL mechanisms' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )
176
- attributetype ( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion' DESC 'RFC2252: supported LDAP versions' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )
177
- attributetype ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension' DESC 'RFC2252: supported extended operations' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
178
- attributetype ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl' DESC 'RFC2252: supported controls' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
179
- attributetype ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts' DESC 'RFC2252: naming contexts' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )
180
- attributetype ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' DESC 'RFC2252: alternative servers' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )
181
- attributetype ( 2.5.18.10 NAME 'subschemaSubentry' DESC 'RFC2252: name of controlling subschema entry' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
182
- attributetype ( 2.5.18.9 NAME 'hasSubordinates' DESC 'X.501: entry has children' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
183
- attributetype ( 2.5.18.4 NAME 'modifiersName' DESC 'RFC2252: name of last modifier' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
184
- attributetype ( 2.5.18.3 NAME 'creatorsName' DESC 'RFC2252: name of creator' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
185
- attributetype ( 2.5.18.2 NAME 'modifyTimestamp' DESC 'RFC2252: time which object was last modified' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
186
- attributetype ( 2.5.18.1 NAME 'createTimestamp' DESC 'RFC2252: time which object was created' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
187
- attributetype ( 2.5.21.9 NAME 'structuralObjectClass' DESC 'X.500(93): structural object class of entry' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
188
- attributetype ( 2.5.4.0 NAME 'objectClass' DESC 'RFC2256: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
189
- # These ones aren't published by OpenLDAP, but are referenced by the 'subschema' objectclass
190
- attributetype ( 2.5.21.1 NAME 'dITStructureRules' EQUALITY integerFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 USAGE directoryOperation )
191
- attributetype ( 2.5.21.7 NAME 'nameForms' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )
192
- attributetype ( 2.5.21.2 NAME 'dITContentRules' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )
193
-
194
- objectclass ( 2.5.20.1 NAME 'subschema' DESC 'RFC2252: controlling subschema (sub)entry' AUXILIARY MAY ( dITStructureRules $ nameForms $ ditContentRules $ objectClasses $ attributeTypes $ matchingRules $ matchingRuleUse ) )
195
- #Don't have definition for subtreeSpecification:
196
- #objectClass ( 2.5.17.0 NAME 'subentry' SUP top STRUCTURAL MUST ( cn $ subtreeSpecification ) )
197
- objectClass ( 1.3.6.1.4.1.4203.1.4.1 NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) DESC 'OpenLDAP Root DSE object' SUP top STRUCTURAL MAY cn )
198
- objectClass ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'namedref: named subordinate referral' SUP top STRUCTURAL MUST ref )
199
- objectClass ( 2.5.6.1 NAME 'alias' DESC 'RFC2256: an alias' SUP top STRUCTURAL MUST aliasedObjectName )
200
- objectClass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject' DESC 'RFC2252: extensible object' SUP top AUXILIARY )
201
- objectClass ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
202
- EOS
203
- end
204
-
205
- # After loading object classes and attr types: resolve oid strings to point
206
- # to objects. This will expose schema inconsistencies (e.g. objectclass
207
- # has unknown SUP class or points to unknown attributeType). However,
208
- # unknown Syntaxes just create new Syntax objects.
209
-
210
- def resolve_oids
211
-
212
- all_attrtypes.each do |a|
213
- if a.sup
214
- s = find_attrtype(a.sup)
215
- a.instance_eval {
216
- @sup = s
217
- # inherit properties (FIXME: This breaks to_def)
218
- @equality ||= s.equality
219
- @ordering ||= s.ordering
220
- @substr ||= s.substr
221
- @syntax ||= s.syntax
222
- @maxlen ||= s.maxlen
223
- @singlevalue ||= s.singlevalue
224
- @collective ||= s.collective
225
- @nousermod ||= s.nousermod
226
- @usage ||= s.usage
227
- }
228
- end
229
- a.instance_eval do
230
- @syntax = LDAP::Server::Syntax.find(@syntax) if @syntax
231
- @equality = LDAP::Server::MatchingRule.find(@equality) if @equality
232
- @ordering = LDAP::Server::MatchingRule.find(@ordering) if @ordering
233
- @substr = LDAP::Server::MatchingRule.find(@substr) if @substr
234
- end
235
- end
236
-
237
- all_objectclasses.each do |o|
238
- if o.sup
239
- s = o.sup.collect { |ss| find_objectclass(ss) }
240
- o.instance_eval { @sup = s }
241
- end
242
- if o.must
243
- s = o.must.collect { |ss| find_attrtype(ss) }
244
- o.instance_eval { @must = s }
245
- end
246
- if o.may
247
- s = o.may.collect { |ss| find_attrtype(ss) }
248
- o.instance_eval { @may = s }
249
- end
250
- end
251
-
252
- end
253
-
254
- # Validate a new entry or update. For a new entry, just pass a hash
255
- # of attr=>[val, val, ...]; for an update, the first parameter is
256
- # a hash of attr=>[:modtype, val, val...] and the second parameter
257
- # is the existing entry, where it is assumed that the attribute names
258
- # are already in their standard string forms (as returned by attr#name)
259
- #
260
- # Returns a hash containing the updated entry.
261
- #
262
- # If a block is given, it is called to decide whether the user is
263
- # allowed to update an attribute; parameter is the attr *object*
264
- # (not name; use #name if you need its name instead). Return false
265
- # if the update is not permitted. Otherwise, the only restriction
266
- # will be that updates to attributes declared 'nousermod' are forbidden.
267
- #
268
- # No DN checks are done here, since we don't know the DN.
269
- # Checking that the entry contains an attribute for the RDN is the
270
- # responsibility of the caller.
271
-
272
- def validate(mods, entry={})
273
-
274
- # Run through the mods, make the normalized names, and perform any
275
- # updates
276
-
277
- # FIXME: I don't know if these are the right results to return
278
- # for the various types of validation errors
279
-
280
- oc_changed = false
281
- res = entry.dup
282
- mods.each do |attrname, nv|
283
- attr = find_attrtype(attrname)
284
- attrname = attr.to_s
285
- raise LDAP::ResultError::ConstraintViolation,
286
- "Cannot modify #{attrname}" if attr.nousermod or
287
- (block_given? and !yield(attr))
288
- # Perform the update
289
- vals = res[attrname] || []
290
- checkvals = []
291
- nv = [nv] unless nv.is_a?(Array)
292
-
293
- case nv.first
294
- when :add
295
- checkvals = nv[1..-1]
296
- vals += checkvals
297
- vals.uniq! # FIXME: ?? error if duplicate values
298
- # FIXME: normalize values? e.g. c: gb and c: GB are same value.
299
- when :delete
300
- nv = nv[1..-1]
301
- if nv.empty?
302
- vals = [] # ?? error if does not exist
303
- else
304
- nv.each { |v| vals.delete(v) } # ?? error if value missing
305
- end
306
- when :replace
307
- vals = checkvals = nv[1..-1]
308
- else
309
- vals = checkvals = nv
310
- end
311
- if vals == []
312
- res.delete(attrname)
313
- else
314
- res[attrname] = vals
315
- end
316
-
317
- # Attribute validation
318
- raise LDAP::ResultError::ObjectClassViolation,
319
- "Attribute #{attr} is SINGLE-VALUE" if attr.singlevalue and vals.size > 1
320
-
321
- checkvals.each do |val|
322
- raise LDAP::ResultError::InvalidAttributeSyntax,
323
- "Nil or empty value for attribute #{attr}" if val.nil? or val.empty?
324
- raise LDAP::ResultError::InvalidAttributeSyntax,
325
- "Bad value for #{attr}: #{val.inspect}" if attr.syntax and ! attr.syntax.match(val)
326
- raise LDAP::ResultError::InvalidAttributeSyntax,
327
- "Value too long for #{attr} (max #{attr.maxlen})" if attr.maxlen and val.length > attr.maxlen
328
- end
329
-
330
- oc_changed = true if attrname == 'objectClass'
331
- end
332
-
333
- # Now do objectClass checks
334
- oc = res['objectClass']
335
- unless oc
336
- raise LDAP::ResultError::ObjectClassViolation,
337
- "objectClass attribute missing"
338
- end
339
- oc = oc.collect { |val| find_objectclass(val) }
340
-
341
- if oc_changed
342
- # Add superior objectClasses (note: growing an array while you
343
- # iterate over it seems to work, in ruby-1.8.2 anyway!)
344
- oc.each do |objectclass|
345
- objectclass.sup.each do |s|
346
- oc.push(s) unless oc.include?(s)
347
- end
348
- end
349
- res['objectClass'] = oc.collect { |oo| oo.to_s }
350
-
351
- # Check that exactly one structural objectClass is present
352
- unless oc.find_all { |s| s.struct == :structural }.size >= 1
353
- raise LDAP::ResultError::ObjectClassViolation,
354
- "Entry must have at least one structural objectClass"
355
- # Exactly one? But you have to sort out the inheritance problem
356
- # (e.g. both person and organizationalPerson are declared
357
- # structural)
358
- end
359
- end
360
-
361
- # Ensure that all MUST attributes are present
362
- allow_attr = {}
363
- oc.each do |objectclass|
364
- objectclass.must.each do |m|
365
- unless res[m.name] and res[m.name] != []
366
- raise LDAP::ResultError::ObjectClassViolation, "Missing attribute #{m} required by objectClass #{objectclass}"
367
- end
368
- allow_attr[m.name] = true
369
- end
370
- objectclass.may.each do |m|
371
- allow_attr[m.name] = true
372
- end
373
- end
374
-
375
- unless oc.find { |objectclass| objectclass.name == 'extensibleObject' }
376
- # Now check all the attributes given are permitted by MUST or MAY
377
- res.each_key do |attr|
378
- unless allow_attr[attr] or find_attrtype(attr).usage == :directoryOperation
379
- raise LDAP::ResultError::ObjectClassViolation, "Attribute #{attr} not permitted by objectClass"
380
- end
381
- end
382
- end
383
-
384
- return res
385
- end
386
-
387
- # Hopefully backwards-compatible API for ruby-ldap's LDAP::Schema.
388
- # Since MUST/MAY/SUP may point to schema objects, convert them back
389
- # to strings.
390
-
391
- def names(key)
392
- case key
393
- when 'objectClasses'
394
- return all_objectclasses.collect { |e| e.name }
395
- when 'attributeTypes'
396
- return all_attrtypes.collect { |e| e.name }
397
- when 'ldapSyntaxes'
398
- return LDAP::Server::Syntax.all_syntaxes.collect { |e| e.name }
399
- when 'matchingRules'
400
- return LDAP::Server::MatchingRule.all_matching_rules.collect { |e| e.name }
401
- # TODO: matchingRuleUse
402
- end
403
- return nil
404
- end
405
-
406
- # Backwards-compatible for ruby-ldap LDAP::Schema
407
-
408
- def attr(oc,at)
409
- o = find_objectclass(oc)
410
- case at.upcase
411
- when 'MUST'
412
- return o.must.collect { |e| e.to_s }
413
- when 'MAY'
414
- return o.may.collect { |e| e.to_s }
415
- when 'SUP'
416
- return o.sup.collect { |e| e.to_s }
417
- when 'NAME'
418
- return o.names.collect { |e| e.to_s }
419
- when 'DESC'
420
- return [o.desc]
421
- end
422
- return nil
423
- rescue LDAP::ResultError
424
- return nil
425
- end
426
-
427
- # Backwards-compatible for ruby-ldap LDAP::Schema
428
-
429
- def must(oc)
430
- attr(oc, "MUST")
431
- end
432
-
433
- # Backwards-compatible for ruby-ldap LDAP::Schema
434
-
435
- def may(oc)
436
- attr(oc, "MAY")
437
- end
438
-
439
- # Backwards-compatible for ruby-ldap LDAP::Schema
440
-
441
- def sup(oc)
442
- attr(oc, "SUP")
443
- end
444
-
445
- #####################################################################
446
-
447
- # Class holding an instance of an AttributeTypeDescription (RFC2252 4.2)
448
-
449
- class AttributeType
450
-
451
- attr_reader :oid, :names, :desc, :obsolete, :sup, :equality, :ordering
452
- attr_reader :substr, :syntax, :maxlen, :singlevalue, :collective
453
- attr_reader :nousermod, :usage
454
-
455
- def initialize(str)
456
- m = LDAP::Server::Syntax::AttributeTypeDescription.match(str)
457
- raise LDAP::ResultError::InvalidAttributeSyntax,
458
- "Bad AttributeTypeDescription #{str.inspect}" unless m
459
- @oid = m[1]
460
- @names = (m[2]||"").scan(/'(.*?)'/).flatten
461
- @desc = m[3]
462
- @obsolete = ! m[4].nil?
463
- @sup = m[5]
464
- @equality = m[6]
465
- @ordering = m[7]
466
- @substr = m[8]
467
- @syntax = m[9]
468
- @maxlen = m[10] && m[10].to_i
469
- @singlevalue = ! m[11].nil?
470
- @collective = ! m[12].nil?
471
- @nousermod = ! m[13].nil?
472
- @usage = m[14] && m[14].intern
473
- # This is the cache of the stringified version. Rather than
474
- # initialize to str, we set nil to force it to be rebuilt
475
- @def = nil
476
- end
477
-
478
- def name
479
- @names.first
480
- end
481
-
482
- def to_s
483
- (@names && @names.first) || @oid
484
- end
485
-
486
- def changed
487
- @def = nil
488
- end
489
-
490
- def to_def
491
- return @def if @def
492
- ans = "( #{@oid} "
493
- if @names.nil? or @names.empty?
494
- # nothing
495
- elsif @names.size == 1
496
- ans << "NAME '#{@names.first}' "
497
- else
498
- ans << "NAME ( "
499
- @names.each { |n| ans << "'#{n}' " }
500
- ans << ") "
501
- end
502
- ans << "DESC '#{@desc}' " if @desc
503
- ans << "OBSOLETE " if @obsolete
504
- ans << "SUP #{@sup} " if @sup # oid
505
- ans << "EQUALITY #{@equality} " if @equality # oid
506
- ans << "ORDERING #{@ordering} " if @ordering # oid
507
- ans << "SUBSTR #{@substr} " if @substr # oid
508
- ans << "SYNTAX #{@syntax}#{@maxlen && "{#{@maxlen}}"} " if @syntax
509
- ans << "SINGLE-VALUE " if @singlevalue
510
- ans << "COLLECTIVE " if @collective
511
- ans << "NO-USER-MODIFICATION " if @nousermod
512
- ans << "USAGE #{@usage} " if @usage
513
- ans << ")"
514
- @def = ans
515
- end
516
- end # class AttributeType
517
-
518
- #####################################################################
519
-
520
- # Class holding an instance of an ObjectClassDescription (RFC2252 4.4)
521
-
522
- class ObjectClass
523
-
524
- attr_reader :oid, :names, :desc, :obsolete, :sup, :struct, :must, :may
525
-
526
- SCAN_WOID = /#{LDAP::Server::Syntax::WOID}/x
527
-
528
- def initialize(str)
529
- m = LDAP::Server::Syntax::ObjectClassDescription.match(str)
530
- raise LDAP::ResultError::InvalidAttributeSyntax,
531
- "Bad ObjectClassDescription #{str.inspect}" unless m
532
- @oid = m[1]
533
- @names = (m[2]||"").scan(/'(.*?)'/).flatten
534
- @desc = m[3]
535
- @obsolete = ! m[4].nil?
536
- @sup = (m[5]||"").scan(SCAN_WOID).flatten
537
- @struct = m[6] ? m[6].downcase.intern : :structural
538
- @must = (m[7]||"").scan(SCAN_WOID).flatten
539
- @may = (m[8]||"").scan(SCAN_WOID).flatten
540
- @def = nil
541
- end
542
-
543
- def name
544
- @names.first
545
- end
546
-
547
- def to_s
548
- (@names && @names.first) || @oid
549
- end
550
-
551
- def changed
552
- @def = nil
553
- end
554
-
555
- def to_def
556
- return @def if @def
557
- ans = "( #{@oid} "
558
- if @names.nil? or @names.empty?
559
- # nothing
560
- elsif @names.size == 1
561
- ans << "NAME '#{@names.first}' "
562
- else
563
- ans << "NAME ( "
564
- @names.each { |n| ans << "'#{n}' " }
565
- ans << ") "
566
- end
567
- ans << "DESC '#{@desc}' " if @desc
568
- ans << "OBSOLETE " if @obsolete
569
- ans << joinoids("SUP ",@sup," ")
570
- ans << "#{@struct.to_s.upcase} " if @struct
571
- ans << joinoids("MUST ",@must," ")
572
- ans << joinoids("MAY ",@may," ")
573
- ans << ")"
574
- @def = ans
575
- end
576
-
577
- def joinoids(pfx,arr,sfx)
578
- return "" unless arr and !arr.empty?
579
- return "#{pfx}#{arr}#{sfx}" unless arr.is_a?(Array)
580
- a = arr.collect { |elem| elem.to_s }
581
- if a.size == 1
582
- return "#{pfx}#{a.first}#{sfx}"
583
- else
584
- return "#{pfx}( #{a.join(" $ ")} )#{sfx}"
585
- end
586
- end
587
- end # class ObjectClass
588
-
589
- end # class Schema
590
-
591
- end # class Server
592
- end # module LDAP