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