| Class | ActiveLdap::Adapter::NetLdap |
| In: |
lib/active_ldap/adapter/net_ldap.rb
|
| Parent: | Base |
| METHOD | = | { :ssl => :simple_tls, :tls => :start_tls, :plain => nil, } |
| CHARS | = | ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a |
# File lib/active_ldap/adapter/net_ldap.rb, line 97
97: def add(dn, entries, options={})
98: super do |_dn, _entries|
99: attributes = {}
100: _entries.each do |type, key, attrs|
101: attrs.each do |name, values|
102: attributes[name] = values
103: end
104: end
105: args = {:dn => _dn, :attributes => attributes}
106: info = args.dup
107: execute(:add, info, args)
108: end
109: end
# File lib/active_ldap/adapter/net_ldap.rb, line 50
50: def bind(options={})
51: begin
52: super
53: rescue Net::LDAP::LdapError
54: raise AuthenticationError, $!.message
55: end
56: end
# File lib/active_ldap/adapter/net_ldap.rb, line 58
58: def bind_as_anonymous(options={})
59: super do
60: execute(:bind, {:name => "bind: anonymous"}, {:method => :anonymous})
61: true
62: end
63: end
# File lib/active_ldap/adapter/net_ldap.rb, line 23
23: def connect(options={})
24: super do |host, port, method|
25: config = {
26: :host => host,
27: :port => port,
28: }
29: config[:encryption] = {:method => method} if method
30: begin
31: uri = construct_uri(host, port, method == :simple_tls)
32: with_start_tls = method == :start_tls
33: info = {:uri => uri, :with_start_tls => with_start_tls}
34: [log("connect", info) {Net::LDAP::Connection.new(config)},
35: uri, with_start_tls]
36: rescue Net::LDAP::LdapError
37: raise ConnectionError, $!.message
38: end
39: end
40: end
# File lib/active_ldap/adapter/net_ldap.rb, line 89
89: def delete(targets, options={})
90: super do |target|
91: args = {:dn => target}
92: info = args.dup
93: execute(:delete, info, args)
94: end
95: end
# File lib/active_ldap/adapter/net_ldap.rb, line 111
111: def modify(dn, entries, options={})
112: super do |_dn, _entries|
113: info = {:dn => _dn, :attributes => _entries}
114: execute(:modify, info,
115: :dn => _dn,
116: :operations => parse_entries(_entries))
117: end
118: end
# File lib/active_ldap/adapter/net_ldap.rb, line 120
120: def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
121: super do |_dn, _new_rdn, _delete_old_rdn, _new_superior|
122: if _new_superior
123: raise NotImplemented.new(_("modify RDN with new superior"))
124: end
125: info = {
126: :name => "modify: RDN",
127: :dn => _dn,
128: :new_rdn => _new_rdn,
129: :new_superior => _new_superior,
130: :delete_old_rdn => _delete_old_rdn
131: }
132: execute(:rename, info,
133: :olddn => _dn,
134: :newrdn => _new_rdn,
135: :delete_attributes => _delete_old_rdn)
136: end
137: end
# File lib/active_ldap/adapter/net_ldap.rb, line 65
65: def search(options={})
66: super(options) do |base, scope, filter, attrs, limit|
67: args = {
68: :base => base,
69: :scope => scope,
70: :filter => filter,
71: :attributes => attrs,
72: :size => limit,
73: }
74: info = {
75: :base => base, :scope => scope_name(scope),
76: :filter => filter, :attributes => attrs, :limit => limit
77: }
78: execute(:search, info, args) do |entry|
79: attributes = {}
80: entry.original_attribute_names.each do |name|
81: value = entry[name]
82: attributes[name] = value if value
83: end
84: yield([entry.dn, attributes])
85: end
86: end
87: end
# File lib/active_ldap/adapter/net_ldap.rb, line 42
42: def unbind(options={})
43: super do
44: log("unbind") do
45: @connection.close # Net::LDAP doesn't implement unbind.
46: end
47: end
48: end
# File lib/active_ldap/adapter/net_ldap.rb, line 163
163: def ensure_method(method)
164: method ||= "plain"
165: normalized_method = method.to_s.downcase.to_sym
166: return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
167:
168: available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
169: format = _("%s is not one of the available connect methods: %s")
170: raise ConfigurationError, format % [method.inspect, available_methods]
171: end
# File lib/active_ldap/adapter/net_ldap.rb, line 299
299: def ensure_mod_type(type)
300: case type
301: when :replace, :add, :delete
302: type
303: else
304: raise ArgumentError, _("unknown type: %s") % type
305: end
306: end
# File lib/active_ldap/adapter/net_ldap.rb, line 173
173: def ensure_scope(scope)
174: scope_map = {
175: :base => Net::LDAP::SearchScope_BaseObject,
176: :sub => Net::LDAP::SearchScope_WholeSubtree,
177: :one => Net::LDAP::SearchScope_SingleLevel,
178: }
179: value = scope_map[scope || :sub]
180: if value.nil?
181: available_scopes = scope_map.keys.inspect
182: format = _("%s is not one of the available LDAP scope: %s")
183: raise ArgumentError, format % [scope.inspect, available_scopes]
184: end
185: value
186: end
# File lib/active_ldap/adapter/net_ldap.rb, line 140
140: def execute(method, info=nil, *args, &block)
141: name = (info || {}).delete(:name) || method
142: result = log(name, info) do
143: begin
144: @connection.send(method, *args, &block)
145: rescue Errno::EPIPE
146: raise ConnectionError, "#{$!.class}: #{$!.message}"
147: end
148: end
149: message = nil
150: if result.is_a?(Hash)
151: message = result[:errorMessage]
152: result = result[:resultCode]
153: end
154: unless result.zero?
155: klass = LdapError::ERRORS[result]
156: klass ||= LdapError
157: return if klass == LdapError::SizeLimitExceeded
158: message = [Net::LDAP.result2string(result), message].compact.join(": ")
159: raise klass, message
160: end
161: end
# File lib/active_ldap/adapter/net_ldap.rb, line 268
268: def generate_client_nonce(size=32)
269: nonce = ""
270: size.times do |i|
271: nonce << CHARS[rand(CHARS.size)]
272: end
273: nonce
274: end
# File lib/active_ldap/adapter/net_ldap.rb, line 288
288: def parse_entries(entries)
289: result = []
290: entries.each do |type, key, attributes|
291: mod_type = ensure_mod_type(type)
292: attributes.each do |name, values|
293: result << [mod_type, name, values]
294: end
295: end
296: result
297: end
# File lib/active_ldap/adapter/net_ldap.rb, line 259
259: def parse_sasl_digest_md5_credential(cred)
260: params = {}
261: cred.scan(/(\w+)=(\"?)(.+?)\2(?:,|$)/) do |name, sep, value|
262: params[name] = value
263: end
264: params
265: end
# File lib/active_ldap/adapter/net_ldap.rb, line 196
196: def sasl_bind(bind_dn, options={})
197: super do |_bind_dn, mechanism, quiet|
198: normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
199: sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
200: next unless respond_to?(sasl_bind_setup, true)
201: initial_credential, challenge_response =
202: send(sasl_bind_setup, _bind_dn, options)
203: args = {
204: :method => :sasl,
205: :initial_credential => initial_credential,
206: :mechanism => mechanism,
207: :challenge_response => challenge_response,
208: }
209: info = {
210: :name => "bind: SASL", :dn => _bind_dn, :mechanism => mechanism,
211: }
212: execute(:bind, info, args)
213: true
214: end
215: end
# File lib/active_ldap/adapter/net_ldap.rb, line 217
217: def sasl_bind_setup_digest_md5(bind_dn, options)
218: initial_credential = ""
219: nonce_count = 1
220: challenge_response = Proc.new do |cred|
221: params = parse_sasl_digest_md5_credential(cred)
222: qops = params["qop"].split(/,/)
223: unless qops.include?("auth")
224: raise ActiveLdap::AuthenticationError,
225: _("unsupported qops: %s") % qops.inspect
226: end
227: qop = "auth"
228: server = @connection.instance_variable_get("@conn").addr[2]
229: realm = params['realm']
230: uri = "ldap/#{server}"
231: nc = "%08x" % nonce_count
232: nonce = params["nonce"]
233: cnonce = generate_client_nonce
234: requests = {
235: :username => bind_dn.inspect,
236: :realm => realm.inspect,
237: :nonce => nonce.inspect,
238: :cnonce => cnonce.inspect,
239: :nc => nc,
240: :qop => qop,
241: :maxbuf => "65536",
242: "digest-uri" => uri.inspect,
243: }
244: a1 = "#{bind_dn}:#{realm}:#{password(cred, options)}"
245: a1 = "#{Digest::MD5.digest(a1)}:#{nonce}:#{cnonce}"
246: ha1 = Digest::MD5.hexdigest(a1)
247: a2 = "AUTHENTICATE:#{uri}"
248: ha2 = Digest::MD5.hexdigest(a2)
249: response = "#{ha1}:#{nonce}:#{nc}:#{cnonce}:#{qop}:#{ha2}"
250: requests["response"] = Digest::MD5.hexdigest(response)
251: nonce_count += 1
252: requests.collect do |key, value|
253: "#{key}=#{value}"
254: end.join(",")
255: end
256: [initial_credential, challenge_response]
257: end
# File lib/active_ldap/adapter/net_ldap.rb, line 188
188: def scope_name(scope)
189: {
190: Net::LDAP::SearchScope_BaseObject => :base,
191: Net::LDAP::SearchScope_WholeSubtree => :sub,
192: Net::LDAP::SearchScope_SingleLevel => :one,
193: }[scope]
194: end
# File lib/active_ldap/adapter/net_ldap.rb, line 276
276: def simple_bind(bind_dn, options={})
277: super do |_bind_dn, password|
278: args = {
279: :method => :simple,
280: :username => _bind_dn,
281: :password => password,
282: }
283: execute(:bind, {:dn => _bind_dn}, args)
284: true
285: end
286: end