Class ActiveLdap::Adapter::Base
In: lib/active_ldap/adapter/base.rb
lib/active_ldap/adapter/jndi.rb
lib/active_ldap/adapter/ldap.rb
lib/active_ldap/adapter/net_ldap.rb
Parent: Object
Error AttributeAssignmentError AdapterNotSpecified OperationNotPermitted RequiredObjectClassMissed ConnectionError RequiredAttributeMissed LdifInvalid LdapError DistinguishedNameNotSetError EntryNotFound SaveError StrongAuthenticationRequired AdapterNotFound ConnectionNotEstablished TimeoutError AuthenticationError AttributeValueInvalid EntryNotSaved DistinguishedNameInputInvalid EntryAlreadyExist ObjectClassError UnknownAttribute EntryInvalid DeleteError ConfigurationError DistinguishedNameInvalid DistinguishedName Base Reloadable::Deprecated Reloadable::Subclasses Enumerable Ldif Collection EntryAttribute StandardError Children HasManyWrap HasMany BelongsToMany Proxy BelongsTo Common Find LDIF Delete Update Normalizable GetText Parser ActiveRecord::Callbacks ActiveRecord::Validations Base\n[lib/active_ldap/adapter/base.rb\nlib/active_ldap/adapter/jndi.rb\nlib/active_ldap/adapter/ldap.rb\nlib/active_ldap/adapter/net_ldap.rb] Jndi Ldap NetLdap GetTextSupport Schema\n[lib/active_ldap/schema.rb\nlib/active_ldap/schema/syntaxes.rb] JndiConnection lib/active_ldap/distinguished_name.rb lib/active_ldap/base.rb lib/active_ldap/schema.rb lib/active_ldap/entry_attribute.rb lib/active_ldap/ldif.rb lib/active_ldap/ldap_error.rb ClassMethods Associations LdapBenchmarking ActionController Populate lib/active_ldap/association/has_many_wrap.rb lib/active_ldap/association/children.rb lib/active_ldap/association/collection.rb lib/active_ldap/association/proxy.rb lib/active_ldap/association/belongs_to_many.rb lib/active_ldap/association/belongs_to.rb lib/active_ldap/association/has_many.rb HasManyUtils Association ClassMethods Tree Acts Command Update Common ModifyNameRecordLoadable AddOperationModifiable DeleteOperationModifiable ReplaceOperationModifiable ModifyRecordLoadable DeleteRecordLoadable AddRecordLoadable ContentRecordLoadable LDIF Delete Find Operations GetTextSupport Escape ClassMethods Normalizable Attributes ClassMethods Configuration ClassMethods ObjectClass lib/active_ldap/get_text/parser.rb GetText ClassMethods Callbacks Validations lib/active_ldap/adapter/jndi_connection.rb lib/active_ldap/adapter/net_ldap.rb lib/active_ldap/adapter/ldap.rb lib/active_ldap/adapter/jndi.rb Adapter Helper GetTextFallback ClassMethods HumanReadable Salt UserPassword ClassMethods Connection ActiveLdap dot/m_44_0.png

Methods

Included Modules

GetTextSupport

Constants

VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :timeout, :retry_on_timeout, :retry_limit, :retry_wait, :bind_dn, :password, :password_block, :try_sasl, :sasl_mechanisms, :sasl_quiet, :allow_anonymous, :store_password, :scope]
LOGICAL_OPERATORS = [:and, :or, :not, :&, :|]

Attributes

runtime  [R] 

Public Class methods

[Source]

    # File lib/active_ldap/adapter/jndi.rb, line 7
 7:         def jndi_connection(options)
 8:           require 'active_ldap/adapter/jndi_connection'
 9:           Jndi.new(options)
10:         end

[Source]

    # File lib/active_ldap/adapter/ldap.rb, line 7
 7:         def ldap_connection(options)
 8:           require 'active_ldap/adapter/ldap_ext'
 9:           Ldap.new(options)
10:         end

[Source]

    # File lib/active_ldap/adapter/net_ldap.rb, line 9
 9:         def net_ldap_connection(options)
10:           require 'active_ldap/adapter/net_ldap_ext'
11:           NetLdap.new(options)
12:         end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 23
23:       def initialize(configuration={})
24:         @runtime = 0
25:         @connection = nil
26:         @disconnected = false
27:         @entry_attributes = {}
28:         @configuration = configuration.dup
29:         @logger = @configuration.delete(:logger)
30:         @configuration.assert_valid_keys(VALID_ADAPTER_CONFIGURATION_KEYS)
31:         VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
32:           instance_variable_set("@#{name}", configuration[name])
33:         end
34:       end

Public Instance methods

[Source]

     # File lib/active_ldap/adapter/base.rb, line 178
178:       def add(dn, entries, options={})
179:         begin
180:           operation(options) do
181:             yield(dn, entries)
182:           end
183:         rescue LdapError::NoSuchObject
184:           raise EntryNotFound, _("No such entry: %s") % dn
185:         rescue LdapError::InvalidDnSyntax
186:           raise DistinguishedNameInvalid.new(dn)
187:         rescue LdapError::AlreadyExists
188:           raise EntryAlreadyExist, _("%s: %s") % [$!.message, dn]
189:         rescue LdapError::StrongAuthRequired
190:           raise StrongAuthenticationRequired, _("%s: %s") % [$!.message, dn]
191:         rescue LdapError::ObjectClassViolation
192:           raise RequiredAttributeMissed, _("%s: %s") % [$!.message, dn]
193:         rescue LdapError::UnwillingToPerform
194:           raise OperationNotPermitted, _("%s: %s") % [$!.message, dn]
195:         end
196:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 62
62:       def bind(options={})
63:         bind_dn = options[:bind_dn] || @bind_dn
64:         try_sasl = options.has_key?(:try_sasl) ? options[:try_sasl] : @try_sasl
65:         if options.has_key?(:allow_anonymous)
66:           allow_anonymous = options[:allow_anonymous]
67:         else
68:           allow_anonymous = @allow_anonymous
69:         end
70:         options = options.merge(:allow_anonymous => allow_anonymous)
71: 
72:         # Rough bind loop:
73:         # Attempt 1: SASL if available
74:         # Attempt 2: SIMPLE with credentials if password block
75:         # Attempt 3: SIMPLE ANONYMOUS if 1 and 2 fail (or pwblock returns '')
76:         if try_sasl and sasl_bind(bind_dn, options)
77:           @logger.info {_('Bound to %s by SASL as %s') % [target, bind_dn]}
78:         elsif simple_bind(bind_dn, options)
79:           @logger.info {_('Bound to %s by simple as %s') % [target, bind_dn]}
80:         elsif allow_anonymous and bind_as_anonymous(options)
81:           @logger.info {_('Bound to %s as anonymous') % target}
82:         else
83:           message = yield if block_given?
84:           message ||= _('All authentication methods for %s exhausted.') % target
85:           raise AuthenticationError, message
86:         end
87: 
88:         bound?
89:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 91
91:       def bind_as_anonymous(options={})
92:         operation(options) do
93:           yield
94:         end
95:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 41
41:       def connect(options={})
42:         host = options[:host] || @host
43:         port = options[:port] || @port
44:         method = ensure_method(options[:method] || @method)
45:         @disconnected = false
46:         @connection, @uri, @with_start_tls = yield(host, port, method)
47:         prepare_connection(options)
48:         bind(options)
49:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 97
97:       def connecting?
98:         !@connection.nil? and !@disconnected
99:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 163
163:       def delete(targets, options={})
164:         targets = [targets] unless targets.is_a?(Array)
165:         return if targets.empty?
166:         target = nil
167:         begin
168:           operation(options) do
169:             targets.each do |target|
170:               yield(target)
171:             end
172:           end
173:         rescue LdapError::NoSuchObject
174:           raise EntryNotFound, _("No such entry: %s") % target
175:         end
176:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 51
51:       def disconnect!(options={})
52:         return if @connection.nil?
53:         unbind(options)
54:         @connection = @uri = @with_start_tls = nil
55:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 127
127:       def entry_attribute(object_classes)
128:         @entry_attributes[object_classes.uniq.sort] ||=
129:           EntryAttribute.new(schema, object_classes)
130:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 216
216:       def log_info(name, runtime, info=nil)
217:         return unless @logger
218:         return unless @logger.debug?
219:         message = "LDAP: #{name} (#{'%f' % runtime})"
220:         @logger.debug(format_log_entry(message, info))
221:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 198
198:       def modify(dn, entries, options={})
199:         begin
200:           operation(options) do
201:             yield(dn, entries)
202:           end
203:         rescue LdapError::UndefinedType
204:           raise
205:         rescue LdapError::ObjectClassViolation
206:           raise RequiredAttributeMissed, _("%s: %s") % [$!.message, dn]
207:         end
208:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 210
210:       def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
211:         operation(options) do
212:           yield(dn, new_rdn, delete_old_rdn, new_superior)
213:         end
214:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 57
57:       def rebind(options={})
58:         unbind(options) if bound?
59:         connect(options)
60:       end

[Source]

    # File lib/active_ldap/adapter/base.rb, line 36
36:       def reset_runtime
37:         runtime, @runtime = @runtime, 0
38:         runtime
39:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 101
101:       def schema(options={})
102:         @schema ||= operation(options) do
103:           base = options[:base]
104:           attrs = options[:attributes]
105: 
106:           attrs ||= [
107:             'objectClasses',
108:             'attributeTypes',
109:             'matchingRules',
110:             'matchingRuleUse',
111:             'dITStructureRules',
112:             'dITContentRules',
113:             'nameForms',
114:             'ldapSyntaxes',
115:             #'extendedAttributeInfo', # if we need RANGE-LOWER/UPPER.
116:           ]
117:           base ||= root_dse_values('subschemaSubentry', options)[0]
118:           base ||= 'cn=schema'
119:           dn, attributes = search(:base => base,
120:                                   :scope => :base,
121:                                   :filter => '(objectClass=subschema)',
122:                                   :attributes => attrs).first
123:           Schema.new(attributes)
124:         end
125:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 132
132:       def search(options={})
133:         filter = parse_filter(options[:filter]) || 'objectClass=*'
134:         attrs = options[:attributes] || []
135:         scope = ensure_scope(options[:scope] || @scope)
136:         base = options[:base]
137:         limit = options[:limit] || 0
138:         limit = nil if limit <= 0
139: 
140:         attrs = attrs.to_a # just in case
141: 
142:         values = []
143:         callback = Proc.new do |value, block|
144:           value = block.call(value) if block
145:           values << value
146:         end
147: 
148:         begin
149:           operation(options) do
150:             yield(base, scope, filter, attrs, limit, callback)
151:           end
152:         rescue LdapError
153:           # Do nothing on failure
154:           @logger.info do
155:             args = [$!.class, $!.message, filter, attrs.inspect]
156:             _("Ignore error %s(%s): filter %s: attributes: %s") % args
157:           end
158:         end
159: 
160:         values
161:       end

Private Instance methods

[Source]

     # File lib/active_ldap/adapter/base.rb, line 511
511:       def assert_filter_logical_operator(operator)
512:         return if operator.nil?
513:         unless filter_logical_operator?(operator)
514:           raise ArgumentError,
515:                 _("invalid logical operator: %s: available operators: %s") %
516:                   [operator.inspect, LOGICAL_OPERATORS.inspect]
517:         end
518:       end

Determine if we have exceed the retry limit or not. True is reconnecting is allowed - False if not.

[Source]

     # File lib/active_ldap/adapter/base.rb, line 567
567:       def can_reconnect?(options={})
568:         retry_limit = options[:retry_limit] || @retry_limit
569:         reconnect_attempts = options[:reconnect_attempts] || 0
570: 
571:         retry_limit < 0 or reconnect_attempts < (retry_limit - 1)
572:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 490
490:       def collection?(object)
491:         !object.is_a?(String) and object.respond_to?(:each)
492:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 427
427:       def construct_component(key, value, operator=nil)
428:         value, options = extract_filter_value_options(value)
429:         comparison_operator = options[:operator] || "="
430:         if collection?(value)
431:           return nil if value.empty?
432:           operator, value = normalize_array_filter(value, operator)
433:           values = []
434:           value.each do |val|
435:             if collection?(val)
436:               values.concat(val.collect {|v| [key, comparison_operator, v]})
437:             else
438:               values << [key, comparison_operator, val]
439:             end
440:           end
441:           values[0] = values[0][1] if filter_logical_operator?(values[0][1])
442:           parse_filter(values, operator)
443:         else
444:           [
445:            "(",
446:            escape_filter_key(key),
447:            comparison_operator,
448:            escape_filter_value(value, options),
449:            ")"
450:           ].join
451:         end
452:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 403
403:       def construct_components(components, operator)
404:         components.collect do |component|
405:           if component.is_a?(Array)
406:             if filter_logical_operator?(component[0])
407:               parse_filter(component)
408:             elsif component.size == 2
409:               key, value = component
410:               if value.is_a?(Hash)
411:                 parse_filter(value, key)
412:               else
413:                 construct_component(key, value, operator)
414:               end
415:             else
416:               construct_component(component[0], component[1..-1], operator)
417:             end
418:           elsif component.is_a?(Symbol)
419:             assert_filter_logical_operator(component)
420:             nil
421:           else
422:             parse_filter(component, operator)
423:           end
424:         end
425:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 475
475:       def construct_filter(components, operator=nil)
476:         operator = normalize_filter_logical_operator(operator)
477:         components = components.compact
478:         case components.size
479:         when 0
480:           nil
481:         when 1
482:           filter = components[0]
483:           filter = "(!#{filter})" if operator == :not
484:           filter
485:         else
486:           "(#{operator == :and ? '&' : '|'}#{components.join})"
487:         end
488:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 588
588:       def construct_uri(host, port, ssl)
589:         protocol = ssl ? "ldaps" : "ldap"
590:         URI.parse("#{protocol}://#{host}:#{port}").to_s
591:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 454
454:       def escape_filter_key(key)
455:         escape_filter_value(key.to_s)
456:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 458
458:       def escape_filter_value(value, options={})
459:         case value
460:         when Numeric, DN
461:           value = value.to_s
462:         when Time
463:           value = Schema::GeneralizedTime.new.normalize_value(value)
464:         end
465:         value.gsub(/(?:[()\\\0]|\*\*?)/) do |s|
466:           if s == "*"
467:             s
468:           else
469:             s = "*" if s == "**"
470:             "\\%02X" % s[0]
471:           end
472:         end
473:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 384
384:       def extract_filter_value_options(value)
385:         options = {}
386:         if value.is_a?(Array)
387:           case value[0]
388:           when Hash
389:             options = value[0]
390:             value = value[1]
391:           when "=", "~=", "<=", "=>"
392:             options[:operator] = value[0]
393:             if value.size > 2
394:               value = value[1..-1]
395:             else
396:               value = value[1]
397:             end
398:           end
399:         end
400:         [value, options]
401:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 495
495:       def filter_logical_operator?(operator)
496:         LOGICAL_OPERATORS.include?(operator)
497:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 624
624:       def format_log_entry(message, info=nil)
625:         if ActiveLdap::Base.colorize_logging
626:           if @@row_even
627:             message_color, dump_color = "4;36;1", "0;1"
628:           else
629:             @@row_even = true
630:             message_color, dump_color = "4;35;1", "0"
631:           end
632:           @@row_even = !@@row_even
633: 
634:           log_entry = "  \e[#{message_color}m#{message}\e[0m"
635:           log_entry << ": \e[#{dump_color}m#{info.inspect}\e[0m" if info
636:           log_entry
637:         else
638:           log_entry = message
639:           log_entry += ": #{info.inspect}" if info
640:           log_entry
641:         end
642:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 602
602:       def log(name, info=nil)
603:         if block_given?
604:           if @logger and @logger.debug?
605:             result = nil
606:             runtime = Benchmark.realtime {result = yield}
607:             @runtime += runtime
608:             log_info(name, runtime, info)
609:             result
610:           else
611:             yield
612:           end
613:         else
614:           log_info(name, info, 0)
615:           nil
616:         end
617:       rescue Exception
618:         log_info("#{name}: FAILED", 0,
619:                  (info || {}).merge(:error => $!.class.name,
620:                                     :error_message => $!.message))
621:         raise
622:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 249
249:       def need_credential_sasl_mechanism?(mechanism)
250:         not %(GSSAPI EXTERNAL ANONYMOUS).include?(mechanism)
251:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 373
373:       def normalize_array_filter(filter, operator=nil)
374:         filter_operator, *components = filter
375:         if filter_logical_operator?(filter_operator)
376:           operator = filter_operator
377:         else
378:           components.unshift(filter_operator)
379:           components = [components] unless filter_operator.is_a?(Array)
380:         end
381:         [operator, components]
382:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 499
499:       def normalize_filter_logical_operator(operator)
500:         assert_filter_logical_operator(operator)
501:         case (operator || :and)
502:         when :and, :&
503:           :and
504:         when :or, :|
505:           :or
506:         else
507:           :not
508:         end
509:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 227
227:       def operation(options)
228:         retried = false
229:         options = options.dup
230:         options[:try_reconnect] = true unless options.has_key?(:try_reconnect)
231:         try_reconnect = false
232:         begin
233:           reconnect_if_need(options)
234:           try_reconnect = options[:try_reconnect]
235:           with_timeout(try_reconnect, options) do
236:             yield
237:           end
238:         rescue Errno::EPIPE, ConnectionError
239:           if try_reconnect and !retried
240:             retried = true
241:             @disconnected = true
242:             retry
243:           else
244:             raise
245:           end
246:         end
247:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 340
340:       def parse_filter(filter, operator=nil)
341:         return nil if filter.nil?
342:         if !filter.is_a?(String) and !filter.respond_to?(:collect)
343:           filter = filter.to_s
344:         end
345: 
346:         case filter
347:         when String
348:           parse_filter_string(filter)
349:         when Hash
350:           components = filter.sort_by {|k, v| k.to_s}.collect do |key, value|
351:             construct_component(key, value, operator)
352:           end
353:           construct_filter(components, operator)
354:         else
355:           operator, components = normalize_array_filter(filter, operator)
356:           components = construct_components(components, operator)
357:           construct_filter(components, operator)
358:         end
359:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 361
361:       def parse_filter_string(filter)
362:         if /\A\s*\z/.match(filter)
363:           nil
364:         else
365:           if filter[0, 1] == "("
366:             filter
367:           else
368:             "(#{filter})"
369:           end
370:         end
371:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 253
253:       def password(bind_dn, options={})
254:         passwd = options[:password] || @password
255:         return passwd if passwd
256: 
257:         password_block = options[:password_block] || @password_block
258:         # TODO: Give a warning to reconnect users with password clearing
259:         # Get the passphrase for the first time, or anew if we aren't storing
260:         if password_block.respond_to?(:call)
261:           passwd = password_block.call(bind_dn)
262:         else
263:           @logger.error {_('password_block not nil or Proc object. Ignoring.')}
264:           return nil
265:         end
266: 
267:         # Store the password for quick reference later
268:         if options.has_key?(:store_password)
269:           store_password = options[:store_password]
270:         else
271:           store_password = @store_password
272:         end
273:         @password = store_password ? passwd : nil
274: 
275:         passwd
276:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 224
224:       def prepare_connection(options)
225:       end

Attempts to reconnect up to the number of times allowed If forced, try once then fail with ConnectionError if not connected.

[Source]

     # File lib/active_ldap/adapter/base.rb, line 522
522:       def reconnect(options={})
523:         options = options.dup
524:         force = options[:force]
525:         retry_limit = options[:retry_limit] || @retry_limit
526:         retry_wait = options[:retry_wait] || @retry_wait
527:         options[:reconnect_attempts] ||= 0
528: 
529:         loop do
530:           unless can_reconnect?(options)
531:             raise ConnectionError,
532:                   _('Giving up trying to reconnect to LDAP server.')
533:           end
534: 
535:           @logger.debug {_('Attempting to reconnect')}
536:           disconnect!
537: 
538:           # Reset the attempts if this was forced.
539:           options[:reconnect_attempts] = 0 if force
540:           options[:reconnect_attempts] += 1 if retry_limit >= 0
541:           begin
542:             connect(options)
543:             break
544:           rescue => detail
545:             @logger.error do
546:               _("Reconnect to server failed: %s\n" \
547:                 "Reconnect to server failed backtrace:\n" \
548:                 "%s") % [detail.exception, detail.backtrace.join("\n")]
549:             end
550:             # Do not loop if forced
551:             raise ConnectionError, detail.message if force
552:           end
553: 
554:           # Sleep before looping
555:           sleep retry_wait
556:         end
557: 
558:         true
559:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 561
561:       def reconnect_if_need(options={})
562:         reconnect(options) if !connecting? and can_reconnect?(options)
563:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 580
580:       def root_dse(attrs, options={})
581:         search(:base => "",
582:                :scope => :base,
583:                :attributes => attrs).collect do |dn, attributes|
584:           attributes
585:         end
586:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 574
574:       def root_dse_values(key, options={})
575:         dse = root_dse([key], options)[0]
576:         return [] if dse.nil?
577:         dse[key] || dse[key.downcase] || []
578:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 289
289:       def sasl_bind(bind_dn, options={})
290:         # Get all SASL mechanisms
291:         mechanisms = operation(options) do
292:           root_dse_values("supportedSASLMechanisms")
293:         end
294: 
295:         if options.has_key?(:sasl_quiet)
296:           sasl_quiet = options[:sasl_quiet]
297:         else
298:           sasl_quiet = @sasl_quiet
299:         end
300: 
301:         sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
302:         sasl_mechanisms.each do |mechanism|
303:           next unless mechanisms.include?(mechanism)
304:           operation(options) do
305:             yield(bind_dn, mechanism, sasl_quiet)
306:             return true if bound?
307:           end
308:         end
309:         false
310:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 312
312:       def simple_bind(bind_dn, options={})
313:         return false unless bind_dn
314: 
315:         passwd = password(bind_dn, options)
316:         return false unless passwd
317: 
318:         if passwd.empty?
319:           if options[:allow_anonymous]
320:             @logger.info {_("Skip simple bind with empty password.")}
321:             return false
322:           else
323:             raise AuthenticationError,
324:                   _("Can't use empty password for simple bind.")
325:           end
326:         end
327: 
328:         begin
329:           operation(options) do
330:             yield(bind_dn, passwd)
331:             bound?
332:           end
333:         rescue LdapError::InvalidDnSyntax
334:           raise DistinguishedNameInvalid.new(bind_dn)
335:         rescue LdapError::InvalidCredentials
336:           false
337:         end
338:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 593
593:       def target
594:         return nil if @uri.nil?
595:         if @with_start_tls
596:           "#{@uri}(StartTLS)"
597:         else
598:           @uri
599:         end
600:       end

[Source]

     # File lib/active_ldap/adapter/base.rb, line 278
278:       def with_timeout(try_reconnect=true, options={}, &block)
279:         begin
280:           Timeout.alarm(@timeout, &block)
281:         rescue Timeout::Error => e
282:           @logger.error {_('Requested action timed out.')}
283:           retry if @retry_on_timeout and try_reconnect and reconnect(options)
284:           @logger.error {e.message}
285:           raise TimeoutError, e.message
286:         end
287:       end

[Validate]