| 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: info = {
122: :name => "modify: RDN",
123: :dn => _dn, :new_rdn => _new_rdn, :delete_old_rdn => _delete_old_rdn,
124: }
125: execute(:rename, info,
126: :olddn => _dn,
127: :newrdn => _new_rdn,
128: :delete_attributes => _delete_old_rdn)
129: end
130: 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,
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 149
149: def ensure_method(method)
150: method ||= "plain"
151: normalized_method = method.to_s.downcase.to_sym
152: return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
153:
154: available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
155: format = _("%s is not one of the available connect methods: %s")
156: raise ConfigurationError, format % [method.inspect, available_methods]
157: end
# File lib/active_ldap/adapter/net_ldap.rb, line 285
285: def ensure_mod_type(type)
286: case type
287: when :replace, :add, :delete
288: type
289: else
290: raise ArgumentError, _("unknown type: %s") % type
291: end
292: end
# File lib/active_ldap/adapter/net_ldap.rb, line 159
159: def ensure_scope(scope)
160: scope_map = {
161: :base => Net::LDAP::SearchScope_BaseObject,
162: :sub => Net::LDAP::SearchScope_WholeSubtree,
163: :one => Net::LDAP::SearchScope_SingleLevel,
164: }
165: value = scope_map[scope || :sub]
166: if value.nil?
167: available_scopes = scope_map.keys.inspect
168: format = _("%s is not one of the available LDAP scope: %s")
169: raise ArgumentError, format % [scope.inspect, available_scopes]
170: end
171: value
172: end
# File lib/active_ldap/adapter/net_ldap.rb, line 133
133: def execute(method, info=nil, *args, &block)
134: name = (info || {}).delete(:name) || method
135: result = log(name, info) {@connection.send(method, *args, &block)}
136: message = nil
137: if result.is_a?(Hash)
138: message = result[:errorMessage]
139: result = result[:resultCode]
140: end
141: unless result.zero?
142: klass = LdapError::ERRORS[result]
143: klass ||= LdapError
144: message = [Net::LDAP.result2string(result), message].compact.join(": ")
145: raise klass, message
146: end
147: end
# File lib/active_ldap/adapter/net_ldap.rb, line 254
254: def generate_client_nonce(size=32)
255: nonce = ""
256: size.times do |i|
257: nonce << CHARS[rand(CHARS.size)]
258: end
259: nonce
260: end
# File lib/active_ldap/adapter/net_ldap.rb, line 274
274: def parse_entries(entries)
275: result = []
276: entries.each do |type, key, attributes|
277: mod_type = ensure_mod_type(type)
278: attributes.each do |name, values|
279: result << [mod_type, name, values]
280: end
281: end
282: result
283: end
# File lib/active_ldap/adapter/net_ldap.rb, line 245
245: def parse_sasl_digest_md5_credential(cred)
246: params = {}
247: cred.scan(/(\w+)=(\"?)(.+?)\2(?:,|$)/) do |name, sep, value|
248: params[name] = value
249: end
250: params
251: end
# File lib/active_ldap/adapter/net_ldap.rb, line 182
182: def sasl_bind(bind_dn, options={})
183: super do |_bind_dn, mechanism, quiet|
184: normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
185: sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
186: next unless respond_to?(sasl_bind_setup, true)
187: initial_credential, challenge_response =
188: send(sasl_bind_setup, _bind_dn, options)
189: args = {
190: :method => :sasl,
191: :initial_credential => initial_credential,
192: :mechanism => mechanism,
193: :challenge_response => challenge_response,
194: }
195: info = {
196: :name => "bind: SASL", :dn => _bind_dn, :mechanism => mechanism,
197: }
198: execute(:bind, info, args)
199: true
200: end
201: end
# File lib/active_ldap/adapter/net_ldap.rb, line 203
203: def sasl_bind_setup_digest_md5(bind_dn, options)
204: initial_credential = ""
205: nonce_count = 1
206: challenge_response = Proc.new do |cred|
207: params = parse_sasl_digest_md5_credential(cred)
208: qops = params["qop"].split(/,/)
209: unless qops.include?("auth")
210: raise ActiveLdap::AuthenticationError,
211: _("unsupported qops: %s") % qops.inspect
212: end
213: qop = "auth"
214: server = @connection.instance_variable_get("@conn").addr[2]
215: realm = params['realm']
216: uri = "ldap/#{server}"
217: nc = "%08x" % nonce_count
218: nonce = params["nonce"]
219: cnonce = generate_client_nonce
220: requests = {
221: :username => bind_dn.inspect,
222: :realm => realm.inspect,
223: :nonce => nonce.inspect,
224: :cnonce => cnonce.inspect,
225: :nc => nc,
226: :qop => qop,
227: :maxbuf => "65536",
228: "digest-uri" => uri.inspect,
229: }
230: a1 = "#{bind_dn}:#{realm}:#{password(cred, options)}"
231: a1 = "#{Digest::MD5.digest(a1)}:#{nonce}:#{cnonce}"
232: ha1 = Digest::MD5.hexdigest(a1)
233: a2 = "AUTHENTICATE:#{uri}"
234: ha2 = Digest::MD5.hexdigest(a2)
235: response = "#{ha1}:#{nonce}:#{nc}:#{cnonce}:#{qop}:#{ha2}"
236: requests["response"] = Digest::MD5.hexdigest(response)
237: nonce_count += 1
238: requests.collect do |key, value|
239: "#{key}=#{value}"
240: end.join(",")
241: end
242: [initial_credential, challenge_response]
243: end
# File lib/active_ldap/adapter/net_ldap.rb, line 174
174: def scope_name(scope)
175: {
176: Net::LDAP::SearchScope_BaseObject => :base,
177: Net::LDAP::SearchScope_WholeSubtree => :sub,
178: Net::LDAP::SearchScope_SingleLevel => :one,
179: }[scope]
180: end
# File lib/active_ldap/adapter/net_ldap.rb, line 262
262: def simple_bind(bind_dn, options={})
263: super do |_bind_dn, password|
264: args = {
265: :method => :simple,
266: :username => _bind_dn,
267: :password => password,
268: }
269: execute(:bind, {:dn => _bind_dn}, args)
270: true
271: end
272: end