@@ -79,6 +79,14 @@ class LDAP
7979# 
8080#  p ldap.get_operation_result 
8181# 
82+ # === Setting connect timeout 
83+ # 
84+ # By default, Net::LDAP uses TCP sockets with a connection timeout of 5 seconds. 
85+ # 
86+ # This value can be tweaked passing the :connect_timeout parameter. 
87+ # i.e. 
88+ #  ldap = Net::LDAP.new ..., 
89+ #                       :connect_timeout => 3 
8290# 
8391# == A Brief Introduction to LDAP 
8492# 
@@ -315,7 +323,14 @@ class Net::LDAP
315323    :constructed  =>  constructed , 
316324  } 
317325
326+   universal  =  { 
327+     constructed : { 
328+       107  =>  :array  #ExtendedResponse (PasswdModifyResponseValue) 
329+     } 
330+   } 
331+ 
318332  AsnSyntax  =  Net ::BER . compile_syntax ( :application  =>  application , 
333+                                       :universal  =>  universal , 
319334                                      :context_specific  =>  context_specific ) 
320335
321336  DefaultHost  =  "127.0.0.1" 
@@ -324,7 +339,8 @@ class Net::LDAP
324339  DefaultTreebase  =  "dc=com" 
325340  DefaultForceNoPage  =  false 
326341
327-   StartTlsOid  =  "1.3.6.1.4.1.1466.20037" 
342+   StartTlsOid  =  '1.3.6.1.4.1.1466.20037' 
343+   PasswdModifyOid  =  '1.3.6.1.4.1.4203.1.11.1' 
328344
329345  # https://tools.ietf.org/html/rfc4511#section-4.1.9 
330346  # https://tools.ietf.org/html/rfc4511#appendix-A 
@@ -461,11 +477,52 @@ def self.result2string(code) #:nodoc:
461477  #   call to #search, that value will override any treebase value you give 
462478  #   here. 
463479  # * :encryption => specifies the encryption to be used in communicating 
464-   #   with the LDAP server. The value is either a Hash containing additional 
465-   #   parameters, or the Symbol :simple_tls, which is equivalent to 
466-   #   specifying the Hash {:method => :simple_tls}. There is a fairly large 
467-   #   range of potential values that may be given for this parameter. See 
468-   #   #encryption for details. 
480+   #   with the LDAP server. The value must be a Hash containing additional 
481+   #   parameters, which consists of two keys: 
482+   #     method: - :simple_tls or :start_tls 
483+   #     options: - Hash of options for that method 
484+   #   The :simple_tls encryption method encrypts <i>all</i> communications 
485+   #   with the LDAP server. It completely establishes SSL/TLS encryption with 
486+   #   the LDAP server before any LDAP-protocol data is exchanged. There is no 
487+   #   plaintext negotiation and no special encryption-request controls are 
488+   #   sent to the server. <i>The :simple_tls option is the simplest, easiest 
489+   #   way to encrypt communications between Net::LDAP and LDAP servers.</i> 
490+   #   It's intended for cases where you have an implicit level of trust in the 
491+   #   authenticity of the LDAP server. No validation of the LDAP server's SSL 
492+   #   certificate is performed. This means that :simple_tls will not produce 
493+   #   errors if the LDAP server's encryption certificate is not signed by a 
494+   #   well-known Certification Authority. If you get communications or 
495+   #   protocol errors when using this option, check with your LDAP server 
496+   #   administrator. Pay particular attention to the TCP port you are 
497+   #   connecting to. It's impossible for an LDAP server to support plaintext 
498+   #   LDAP communications and <i>simple TLS</i> connections on the same port. 
499+   #   The standard TCP port for unencrypted LDAP connections is 389, but the 
500+   #   standard port for simple-TLS encrypted connections is 636. Be sure you 
501+   #   are using the correct port. 
502+   # 
503+   #   The :start_tls like the :simple_tls encryption method also encrypts all 
504+   #   communcations with the LDAP server. With the exception that it operates 
505+   #   over the standard TCP port. 
506+   # 
507+   #   In order to verify certificates and enable other TLS options, the 
508+   #   :tls_options hash can be passed alongside :simple_tls or :start_tls. 
509+   #   This hash contains any options that can be passed to 
510+   #   OpenSSL::SSL::SSLContext#set_params(). The most common options passed 
511+   #   should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, 
512+   #   which contains a path to a Certificate Authority file (PEM-encoded). 
513+   # 
514+   #   Example for a default setup without custom settings: 
515+   #     { 
516+   #       :method => :simple_tls, 
517+   #       :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS 
518+   #     } 
519+   # 
520+   #   Example for specifying a CA-File and only allowing TLSv1.1 connections: 
521+   # 
522+   #     { 
523+   #       :method => :start_tls, 
524+   #       :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } 
525+   #     } 
469526  # * :force_no_page => Set to true to prevent paged results even if your 
470527  #   server says it supports them. This is a fix for MS Active Directory 
471528  # * :instrumentation_service => An object responsible for instrumenting 
@@ -482,7 +539,8 @@ def initialize(args = {})
482539    @auth  =  args [ :auth ]  || DefaultAuth 
483540    @base  =  args [ :base ]  || DefaultTreebase 
484541    @force_no_page  =  args [ :force_no_page ]  || DefaultForceNoPage 
485-     encryption  args [ :encryption ]  # may be nil 
542+     @encryption  =  args [ :encryption ]  # may be nil 
543+     @connect_timeout  =  args [ :connect_timeout ] 
486544
487545    if  pr  =  @auth [ :password ]  and  pr . respond_to? ( :call ) 
488546      @auth [ :password ]  =  pr . call 
@@ -546,52 +604,16 @@ def authenticate(username, password)
546604  # additional capabilities are added, more configuration values will be 
547605  # added here. 
548606  # 
549-   # The :simple_tls encryption method encrypts <i>all</i> communications 
550-   # with the LDAP server. It completely establishes SSL/TLS encryption with 
551-   # the LDAP server before any LDAP-protocol data is exchanged. There is no 
552-   # plaintext negotiation and no special encryption-request controls are 
553-   # sent to the server. <i>The :simple_tls option is the simplest, easiest 
554-   # way to encrypt communications between Net::LDAP and LDAP servers.</i> 
555-   # It's intended for cases where you have an implicit level of trust in the 
556-   # authenticity of the LDAP server. No validation of the LDAP server's SSL 
557-   # certificate is performed. This means that :simple_tls will not produce 
558-   # errors if the LDAP server's encryption certificate is not signed by a 
559-   # well-known Certification Authority. If you get communications or 
560-   # protocol errors when using this option, check with your LDAP server 
561-   # administrator. Pay particular attention to the TCP port you are 
562-   # connecting to. It's impossible for an LDAP server to support plaintext 
563-   # LDAP communications and <i>simple TLS</i> connections on the same port. 
564-   # The standard TCP port for unencrypted LDAP connections is 389, but the 
565-   # standard port for simple-TLS encrypted connections is 636. Be sure you 
566-   # are using the correct port. 
567-   # 
568-   # The :start_tls like the :simple_tls encryption method also encrypts all 
569-   # communcations with the LDAP server. With the exception that it operates 
570-   # over the standard TCP port. 
571-   # 
572-   # In order to verify certificates and enable other TLS options, the 
573-   # :tls_options hash can be passed alongside :simple_tls or :start_tls. 
574-   # This hash contains any options that can be passed to 
575-   # OpenSSL::SSL::SSLContext#set_params(). The most common options passed 
576-   # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option, 
577-   # which contains a path to a Certificate Authority file (PEM-encoded). 
578-   # 
579-   # Example for a default setup without custom settings: 
580-   #   { 
581-   #     :method => :simple_tls, 
582-   #     :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS 
583-   #   } 
584-   # 
585-   # Example for specifying a CA-File and only allowing TLSv1.1 connections: 
586-   # 
587-   #   { 
588-   #     :method => :start_tls, 
589-   #     :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" } 
590-   #   } 
607+   # This method is deprecated. 
608+   # 
591609  def  encryption ( args ) 
592-     case  args 
610+     warn  "Deprecation warning: please give :encryption option as a Hash to Net::LDAP.new" 
611+     return  if  args . nil? 
612+     return  @encryption  =  args  if  args . is_a?  Hash 
613+ 
614+     case  method  =  args . to_sym 
593615    when  :simple_tls ,  :start_tls 
594-       args  =  {  :method  =>  args ,  :tls_options  =>  { }  } 
616+       args  =  {  :method  =>  method ,  :tls_options  =>  { }  } 
595617    end 
596618    @encryption  =  args 
597619  end 
@@ -637,8 +659,11 @@ def self.open(args)
637659  #++ 
638660  def  get_operation_result 
639661    result  =  @result 
640-     result  =  result . result  if  result . is_a? ( Net ::LDAP ::PDU ) 
641662    os  =  OpenStruct . new 
663+     if  result . is_a? ( Net ::LDAP ::PDU ) 
664+       os . extended_response  =  result . extended_response 
665+       result  =  result . result 
666+     end 
642667    if  result . is_a? ( Hash ) 
643668      # We might get a hash of LDAP response codes instead of a simple 
644669      # numeric code. 
@@ -1027,6 +1052,44 @@ def modify(args)
10271052    end 
10281053  end 
10291054
1055+   # Password Modify 
1056+   # 
1057+   # Change existing password: 
1058+   # 
1059+   #  dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' 
1060+   #  auth = { 
1061+   #    method: :simple, 
1062+   #    username: dn, 
1063+   #    password: 'passworD1' 
1064+   #  } 
1065+   #  ldap.password_modify(dn: dn, 
1066+   #                       auth: auth, 
1067+   #                       old_password: 'passworD1', 
1068+   #                       new_password: 'passworD2') 
1069+   # 
1070+   # Or get the LDAP server to generate a password for you: 
1071+   # 
1072+   #  dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' 
1073+   #  auth = { 
1074+   #    method: :simple, 
1075+   #    username: dn, 
1076+   #    password: 'passworD1' 
1077+   #  } 
1078+   #  ldap.password_modify(dn: dn, 
1079+   #                       auth: auth, 
1080+   #                       old_password: 'passworD1') 
1081+   # 
1082+   #  ldap.get_operation_result.extended_response[0][0] #=> 'VtcgGf/G' 
1083+   # 
1084+   def  password_modify ( args ) 
1085+     instrument  "modify_password.net_ldap" ,  args  do  |payload |
1086+       @result  =  use_connection ( args )  do  |conn |
1087+         conn . password_modify ( args ) 
1088+       end 
1089+       @result . success? 
1090+     end 
1091+   end 
1092+ 
10301093  # Add a value to an attribute. Takes the full DN of the entry to modify, 
10311094  # the name (Symbol or String) of the attribute, and the value (String or 
10321095  # Array). If the attribute does not exist (and there are no schema 
@@ -1247,12 +1310,13 @@ def new_connection
12471310      :port                     =>  @port , 
12481311      :hosts                    =>  @hosts , 
12491312      :encryption               =>  @encryption , 
1250-       :instrumentation_service  =>  @instrumentation_service 
1313+       :instrumentation_service  =>  @instrumentation_service , 
1314+       :connect_timeout          =>  @connect_timeout 
12511315
12521316    # Force connect to see if there's a connection error 
12531317    connection . socket 
12541318    connection 
1255-   rescue  Errno ::ECONNREFUSED ,  Net ::LDAP ::ConnectionRefusedError  =>  e 
1319+   rescue  Errno ::ECONNREFUSED ,  Errno :: ETIMEDOUT ,   Net ::LDAP ::ConnectionRefusedError  =>  e 
12561320    @result  =  { 
12571321      :resultCode    =>  52 , 
12581322      :errorMessage  =>  ResultStrings [ ResultCodeUnavailable ] 
0 commit comments