| 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 96
96: def add(dn, entries, options={})
97: super do |_dn, _entries|
98: attributes = {}
99: _entries.each do |type, key, attrs|
100: attrs.each do |name, values|
101: attributes[name] = values
102: end
103: end
104: args = {:dn => _dn, :attributes => attributes}
105: info = args.dup
106: execute(:add, info, args)
107: end
108: 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 88
88: def delete(targets, options={})
89: super do |target|
90: args = {:dn => target}
91: info = args.dup
92: execute(:delete, info, args)
93: end
94: end
# File lib/active_ldap/adapter/net_ldap.rb, line 110
110: def modify(dn, entries, options={})
111: super do |_dn, _entries|
112: info = {:dn => _dn, :attributes => _entries}
113: execute(:modify, info,
114: :dn => _dn,
115: :operations => parse_entries(_entries))
116: end
117: end
# File lib/active_ldap/adapter/net_ldap.rb, line 119
119: def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
120: super do |_dn, _new_rdn, _delete_old_rdn, _new_superior|
121: if _new_superior
122: raise NotImplemented.new(_("modify RDN with new superior"))
123: end
124: info = {
125: :name => "modify: RDN",
126: :dn => _dn,
127: :new_rdn => _new_rdn,
128: :new_superior => _new_superior,
129: :delete_old_rdn => _delete_old_rdn
130: }
131: execute(:rename, info,
132: :olddn => _dn,
133: :newrdn => _new_rdn,
134: :delete_attributes => _delete_old_rdn)
135: end
136: end
# File lib/active_ldap/adapter/net_ldap.rb, line 65
65: def search(options={}, &block)
66: super(options) do |base, scope, filter, attrs, limit, callback|
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: attributes[name] = entry[name]
82: end
83: callback.call([entry.dn, attributes], block)
84: end
85: end
86: 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 162
162: def ensure_method(method)
163: method ||= "plain"
164: normalized_method = method.to_s.downcase.to_sym
165: return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
166:
167: available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
168: format = _("%s is not one of the available connect methods: %s")
169: raise ConfigurationError, format % [method.inspect, available_methods]
170: end
# File lib/active_ldap/adapter/net_ldap.rb, line 298
298: def ensure_mod_type(type)
299: case type
300: when :replace, :add, :delete
301: type
302: else
303: raise ArgumentError, _("unknown type: %s") % type
304: end
305: end
# File lib/active_ldap/adapter/net_ldap.rb, line 172
172: def ensure_scope(scope)
173: scope_map = {
174: :base => Net::LDAP::SearchScope_BaseObject,
175: :sub => Net::LDAP::SearchScope_WholeSubtree,
176: :one => Net::LDAP::SearchScope_SingleLevel,
177: }
178: value = scope_map[scope || :sub]
179: if value.nil?
180: available_scopes = scope_map.keys.inspect
181: format = _("%s is not one of the available LDAP scope: %s")
182: raise ArgumentError, format % [scope.inspect, available_scopes]
183: end
184: value
185: end
# File lib/active_ldap/adapter/net_ldap.rb, line 139
139: def execute(method, info=nil, *args, &block)
140: name = (info || {}).delete(:name) || method
141: result = log(name, info) do
142: begin
143: @connection.send(method, *args, &block)
144: rescue Errno::EPIPE
145: raise ConnectionError, "#{$!.class}: #{$!.message}"
146: end
147: end
148: message = nil
149: if result.is_a?(Hash)
150: message = result[:errorMessage]
151: result = result[:resultCode]
152: end
153: unless result.zero?
154: klass = LdapError::ERRORS[result]
155: klass ||= LdapError
156: return if klass == LdapError::SizeLimitExceeded
157: message = [Net::LDAP.result2string(result), message].compact.join(": ")
158: raise klass, message
159: end
160: end
# File lib/active_ldap/adapter/net_ldap.rb, line 267
267: def generate_client_nonce(size=32)
268: nonce = ""
269: size.times do |i|
270: nonce << CHARS[rand(CHARS.size)]
271: end
272: nonce
273: end
# File lib/active_ldap/adapter/net_ldap.rb, line 287
287: def parse_entries(entries)
288: result = []
289: entries.each do |type, key, attributes|
290: mod_type = ensure_mod_type(type)
291: attributes.each do |name, values|
292: result << [mod_type, name, values]
293: end
294: end
295: result
296: end
# File lib/active_ldap/adapter/net_ldap.rb, line 258
258: def parse_sasl_digest_md5_credential(cred)
259: params = {}
260: cred.scan(/(\w+)=(\"?)(.+?)\2(?:,|$)/) do |name, sep, value|
261: params[name] = value
262: end
263: params
264: end
# File lib/active_ldap/adapter/net_ldap.rb, line 195
195: def sasl_bind(bind_dn, options={})
196: super do |_bind_dn, mechanism, quiet|
197: normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
198: sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
199: next unless respond_to?(sasl_bind_setup, true)
200: initial_credential, challenge_response =
201: send(sasl_bind_setup, _bind_dn, options)
202: args = {
203: :method => :sasl,
204: :initial_credential => initial_credential,
205: :mechanism => mechanism,
206: :challenge_response => challenge_response,
207: }
208: info = {
209: :name => "bind: SASL", :dn => _bind_dn, :mechanism => mechanism,
210: }
211: execute(:bind, info, args)
212: true
213: end
214: end
# File lib/active_ldap/adapter/net_ldap.rb, line 216
216: def sasl_bind_setup_digest_md5(bind_dn, options)
217: initial_credential = ""
218: nonce_count = 1
219: challenge_response = Proc.new do |cred|
220: params = parse_sasl_digest_md5_credential(cred)
221: qops = params["qop"].split(/,/)
222: unless qops.include?("auth")
223: raise ActiveLdap::AuthenticationError,
224: _("unsupported qops: %s") % qops.inspect
225: end
226: qop = "auth"
227: server = @connection.instance_variable_get("@conn").addr[2]
228: realm = params['realm']
229: uri = "ldap/#{server}"
230: nc = "%08x" % nonce_count
231: nonce = params["nonce"]
232: cnonce = generate_client_nonce
233: requests = {
234: :username => bind_dn.inspect,
235: :realm => realm.inspect,
236: :nonce => nonce.inspect,
237: :cnonce => cnonce.inspect,
238: :nc => nc,
239: :qop => qop,
240: :maxbuf => "65536",
241: "digest-uri" => uri.inspect,
242: }
243: a1 = "#{bind_dn}:#{realm}:#{password(cred, options)}"
244: a1 = "#{Digest::MD5.digest(a1)}:#{nonce}:#{cnonce}"
245: ha1 = Digest::MD5.hexdigest(a1)
246: a2 = "AUTHENTICATE:#{uri}"
247: ha2 = Digest::MD5.hexdigest(a2)
248: response = "#{ha1}:#{nonce}:#{nc}:#{cnonce}:#{qop}:#{ha2}"
249: requests["response"] = Digest::MD5.hexdigest(response)
250: nonce_count += 1
251: requests.collect do |key, value|
252: "#{key}=#{value}"
253: end.join(",")
254: end
255: [initial_credential, challenge_response]
256: end
# File lib/active_ldap/adapter/net_ldap.rb, line 187
187: def scope_name(scope)
188: {
189: Net::LDAP::SearchScope_BaseObject => :base,
190: Net::LDAP::SearchScope_WholeSubtree => :sub,
191: Net::LDAP::SearchScope_SingleLevel => :one,
192: }[scope]
193: end
# File lib/active_ldap/adapter/net_ldap.rb, line 275
275: def simple_bind(bind_dn, options={})
276: super do |_bind_dn, password|
277: args = {
278: :method => :simple,
279: :username => _bind_dn,
280: :password => password,
281: }
282: execute(:bind, {:dn => _bind_dn}, args)
283: true
284: end
285: end