net-ldap 0.11 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of net-ldap might be problematic. Click here for more details.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +15 -0
  3. data/.rubocop_todo.yml +471 -180
  4. data/.travis.yml +10 -5
  5. data/Contributors.rdoc +1 -0
  6. data/History.rdoc +60 -0
  7. data/README.rdoc +18 -11
  8. data/Rakefile +0 -1
  9. data/lib/net/ber/ber_parser.rb +4 -4
  10. data/lib/net/ber/core_ext/array.rb +1 -1
  11. data/lib/net/ber/core_ext/integer.rb +1 -1
  12. data/lib/net/ber/core_ext/string.rb +1 -1
  13. data/lib/net/ber.rb +37 -5
  14. data/lib/net/ldap/auth_adapter/gss_spnego.rb +41 -0
  15. data/lib/net/ldap/auth_adapter/sasl.rb +62 -0
  16. data/lib/net/ldap/auth_adapter/simple.rb +34 -0
  17. data/lib/net/ldap/auth_adapter.rb +29 -0
  18. data/lib/net/ldap/connection.rb +197 -187
  19. data/lib/net/ldap/dataset.rb +2 -2
  20. data/lib/net/ldap/dn.rb +4 -5
  21. data/lib/net/ldap/entry.rb +4 -5
  22. data/lib/net/ldap/error.rb +36 -1
  23. data/lib/net/ldap/filter.rb +6 -6
  24. data/lib/net/ldap/pdu.rb +26 -2
  25. data/lib/net/ldap/version.rb +1 -1
  26. data/lib/net/ldap.rb +189 -75
  27. data/lib/net/snmp.rb +18 -18
  28. data/net-ldap.gemspec +4 -2
  29. data/script/changelog +47 -0
  30. data/script/generate-fixture-ca +48 -0
  31. data/script/install-openldap +67 -44
  32. data/test/ber/core_ext/test_array.rb +1 -1
  33. data/test/ber/test_ber.rb +11 -3
  34. data/test/fixtures/ca/ca.info +4 -0
  35. data/test/fixtures/ca/cacert.pem +24 -0
  36. data/test/fixtures/ca/cakey.pem +190 -0
  37. data/test/fixtures/openldap/slapd.conf.ldif +1 -1
  38. data/test/integration/test_add.rb +1 -1
  39. data/test/integration/test_ber.rb +1 -1
  40. data/test/integration/test_bind.rb +220 -10
  41. data/test/integration/test_delete.rb +1 -1
  42. data/test/integration/test_open.rb +1 -1
  43. data/test/integration/test_password_modify.rb +80 -0
  44. data/test/integration/test_search.rb +1 -1
  45. data/test/support/vm/openldap/README.md +35 -3
  46. data/test/support/vm/openldap/Vagrantfile +1 -0
  47. data/test/test_auth_adapter.rb +15 -0
  48. data/test/test_dn.rb +3 -3
  49. data/test/test_filter.rb +4 -4
  50. data/test/test_filter_parser.rb +4 -0
  51. data/test/test_helper.rb +10 -2
  52. data/test/test_ldap.rb +64 -10
  53. data/test/test_ldap_connection.rb +115 -28
  54. data/test/test_ldif.rb +11 -11
  55. data/test/test_search.rb +2 -2
  56. data/test/test_snmp.rb +4 -4
  57. data/testserver/ldapserver.rb +11 -12
  58. metadata +50 -8
  59. data/test/fixtures/cacert.pem +0 -20
data/lib/net/ldap/pdu.rb CHANGED
@@ -74,6 +74,7 @@ class Net::LDAP::PDU
74
74
  attr_reader :search_referrals
75
75
  attr_reader :search_parameters
76
76
  attr_reader :bind_parameters
77
+ attr_reader :extended_response
77
78
 
78
79
  ##
79
80
  # Returns RFC-2251 Controls if any.
@@ -120,7 +121,7 @@ class Net::LDAP::PDU
120
121
  when UnbindRequest
121
122
  parse_unbind_request(ber_object[1])
122
123
  when ExtendedResponse
123
- parse_ldap_result(ber_object[1])
124
+ parse_extended_response(ber_object[1])
124
125
  else
125
126
  raise LdapPduError.new("unknown pdu-type: #{@app_tag}")
126
127
  end
@@ -174,12 +175,35 @@ class Net::LDAP::PDU
174
175
  @ldap_result = {
175
176
  :resultCode => sequence[0],
176
177
  :matchedDN => sequence[1],
177
- :errorMessage => sequence[2]
178
+ :errorMessage => sequence[2],
178
179
  }
179
180
  parse_search_referral(sequence[3]) if @ldap_result[:resultCode] == Net::LDAP::ResultCodeReferral
180
181
  end
181
182
  private :parse_ldap_result
182
183
 
184
+ ##
185
+ # Parse an extended response
186
+ #
187
+ # http://www.ietf.org/rfc/rfc2251.txt
188
+ #
189
+ # Each Extended operation consists of an Extended request and an
190
+ # Extended response.
191
+ #
192
+ # ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
193
+ # requestName [0] LDAPOID,
194
+ # requestValue [1] OCTET STRING OPTIONAL }
195
+
196
+ def parse_extended_response(sequence)
197
+ sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length."
198
+ @ldap_result = {
199
+ :resultCode => sequence[0],
200
+ :matchedDN => sequence[1],
201
+ :errorMessage => sequence[2],
202
+ }
203
+ @extended_response = sequence[3]
204
+ end
205
+ private :parse_extended_response
206
+
183
207
  ##
184
208
  # A Bind Response may have an additional field, ID [7], serverSaslCreds,
185
209
  # per RFC 2251 pgh 4.2.3.
@@ -1,5 +1,5 @@
1
1
  module Net
2
2
  class LDAP
3
- VERSION = "0.11"
3
+ VERSION = "0.16.0"
4
4
  end
5
5
  end
data/lib/net/ldap.rb CHANGED
@@ -27,6 +27,12 @@ require 'net/ldap/instrumentation'
27
27
  require 'net/ldap/connection'
28
28
  require 'net/ldap/version'
29
29
  require 'net/ldap/error'
30
+ require 'net/ldap/auth_adapter'
31
+ require 'net/ldap/auth_adapter/simple'
32
+ require 'net/ldap/auth_adapter/sasl'
33
+
34
+ Net::LDAP::AuthAdapter.register([:simple, :anon, :anonymous], Net::LDAP::AuthAdapter::Simple)
35
+ Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapter::Sasl)
30
36
 
31
37
  # == Quick-start for the Impatient
32
38
  # === Quick Example of a user-authentication against an LDAP directory:
@@ -73,6 +79,14 @@ require 'net/ldap/error'
73
79
  #
74
80
  # p ldap.get_operation_result
75
81
  #
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
76
90
  #
77
91
  # == A Brief Introduction to LDAP
78
92
  #
@@ -250,14 +264,14 @@ class Net::LDAP
250
264
  SearchScope_BaseObject = 0
251
265
  SearchScope_SingleLevel = 1
252
266
  SearchScope_WholeSubtree = 2
253
- SearchScopes = [ SearchScope_BaseObject, SearchScope_SingleLevel,
254
- SearchScope_WholeSubtree ]
267
+ SearchScopes = [SearchScope_BaseObject, SearchScope_SingleLevel,
268
+ SearchScope_WholeSubtree]
255
269
 
256
270
  DerefAliases_Never = 0
257
271
  DerefAliases_Search = 1
258
272
  DerefAliases_Find = 2
259
273
  DerefAliases_Always = 3
260
- DerefAliasesArray = [ DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always ]
274
+ DerefAliasesArray = [DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always]
261
275
 
262
276
  primitive = { 2 => :null } # UnbindRequest body
263
277
  constructed = {
@@ -309,7 +323,14 @@ class Net::LDAP
309
323
  :constructed => constructed,
310
324
  }
311
325
 
326
+ universal = {
327
+ constructed: {
328
+ 107 => :array, #ExtendedResponse (PasswdModifyResponseValue)
329
+ },
330
+ }
331
+
312
332
  AsnSyntax = Net::BER.compile_syntax(:application => application,
333
+ :universal => universal,
313
334
  :context_specific => context_specific)
314
335
 
315
336
  DefaultHost = "127.0.0.1"
@@ -318,7 +339,8 @@ class Net::LDAP
318
339
  DefaultTreebase = "dc=com"
319
340
  DefaultForceNoPage = false
320
341
 
321
- 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'
322
344
 
323
345
  # https://tools.ietf.org/html/rfc4511#section-4.1.9
324
346
  # https://tools.ietf.org/html/rfc4511#appendix-A
@@ -367,14 +389,14 @@ class Net::LDAP
367
389
  ResultCodeCompareFalse,
368
390
  ResultCodeCompareTrue,
369
391
  ResultCodeReferral,
370
- ResultCodeSaslBindInProgress
392
+ ResultCodeSaslBindInProgress,
371
393
  ]
372
394
 
373
395
  # nonstandard list of "successful" result codes for searches
374
396
  ResultCodesSearchSuccess = [
375
397
  ResultCodeSuccess,
376
398
  ResultCodeTimeLimitExceeded,
377
- ResultCodeSizeLimitExceeded
399
+ ResultCodeSizeLimitExceeded,
378
400
  ]
379
401
 
380
402
  # map of result code to human message
@@ -416,7 +438,7 @@ class Net::LDAP
416
438
  ResultCodeEntryAlreadyExists => "Entry Already Exists",
417
439
  ResultCodeObjectClassModsProhibited => "ObjectClass Modifications Prohibited",
418
440
  ResultCodeAffectsMultipleDSAs => "Affects Multiple DSAs",
419
- ResultCodeOther => "Other"
441
+ ResultCodeOther => "Other",
420
442
  }
421
443
 
422
444
  module LDAPControls
@@ -432,6 +454,7 @@ class Net::LDAP
432
454
 
433
455
  attr_accessor :host
434
456
  attr_accessor :port
457
+ attr_accessor :hosts
435
458
  attr_accessor :base
436
459
 
437
460
  # Instantiate an object of type Net::LDAP to perform directory operations.
@@ -440,6 +463,8 @@ class Net::LDAP
440
463
  # described below. The following arguments are supported:
441
464
  # * :host => the LDAP server's IP-address (default 127.0.0.1)
442
465
  # * :port => the LDAP server's TCP port (default 389)
466
+ # * :hosts => an enumerable of pairs of hosts and corresponding ports with
467
+ # which to attempt opening connections (default [[host, port]])
443
468
  # * :auth => a Hash containing authorization parameters. Currently
444
469
  # supported values include: {:method => :anonymous} and {:method =>
445
470
  # :simple, :username => your_user_name, :password => your_password }
@@ -451,28 +476,83 @@ class Net::LDAP
451
476
  # specify a treebase. If you give a treebase value in any particular
452
477
  # call to #search, that value will override any treebase value you give
453
478
  # here.
454
- # * :encryption => specifies the encryption to be used in communicating
455
- # with the LDAP server. The value is either a Hash containing additional
456
- # parameters, or the Symbol :simple_tls, which is equivalent to
457
- # specifying the Hash {:method => :simple_tls}. There is a fairly large
458
- # range of potential values that may be given for this parameter. See
459
- # #encryption for details.
460
479
  # * :force_no_page => Set to true to prevent paged results even if your
461
480
  # server says it supports them. This is a fix for MS Active Directory
462
481
  # * :instrumentation_service => An object responsible for instrumenting
463
482
  # operations, compatible with ActiveSupport::Notifications' public API.
483
+ # * :encryption => specifies the encryption to be used in communicating
484
+ # with the LDAP server. The value must be a Hash containing additional
485
+ # parameters, which consists of two keys:
486
+ # method: - :simple_tls or :start_tls
487
+ # tls_options: - Hash of options for that method
488
+ # The :simple_tls encryption method encrypts <i>all</i> communications
489
+ # with the LDAP server. It completely establishes SSL/TLS encryption with
490
+ # the LDAP server before any LDAP-protocol data is exchanged. There is no
491
+ # plaintext negotiation and no special encryption-request controls are
492
+ # sent to the server. <i>The :simple_tls option is the simplest, easiest
493
+ # way to encrypt communications between Net::LDAP and LDAP servers.</i>
494
+ # If you get communications or protocol errors when using this option,
495
+ # check with your LDAP server administrator. Pay particular attention
496
+ # to the TCP port you are connecting to. It's impossible for an LDAP
497
+ # server to support plaintext LDAP communications and <i>simple TLS</i>
498
+ # connections on the same port. The standard TCP port for unencrypted
499
+ # LDAP connections is 389, but the standard port for simple-TLS
500
+ # encrypted connections is 636. Be sure you are using the correct port.
501
+ # The :start_tls like the :simple_tls encryption method also encrypts all
502
+ # communcations with the LDAP server. With the exception that it operates
503
+ # over the standard TCP port.
504
+ #
505
+ # To validate the LDAP server's certificate (a security must if you're
506
+ # talking over the public internet), you need to set :tls_options
507
+ # something like this...
508
+ #
509
+ # Net::LDAP.new(
510
+ # # ... set host, bind dn, etc ...
511
+ # encryption: {
512
+ # method: :simple_tls,
513
+ # tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS,
514
+ # }
515
+ # )
516
+ #
517
+ # The above will use the operating system-provided store of CA
518
+ # certificates to validate your LDAP server's cert.
519
+ # If cert validation fails, it'll happen during the #bind
520
+ # whenever you first try to open a connection to the server.
521
+ # Those methods will throw Net::LDAP::ConnectionError with
522
+ # a message about certificate verify failing. If your
523
+ # LDAP server's certificate is signed by DigiCert, Comodo, etc.,
524
+ # you're probably good. If you've got a self-signed cert but it's
525
+ # been added to the host's OS-maintained CA store (e.g. on Debian
526
+ # add foobar.crt to /usr/local/share/ca-certificates/ and run
527
+ # `update-ca-certificates`), then the cert should pass validation.
528
+ # To ignore the OS's CA store, put your CA in a PEM-encoded file and...
529
+ #
530
+ # encryption: {
531
+ # method: :simple_tls,
532
+ # tls_options: { ca_file: '/path/to/my-little-ca.pem',
533
+ # ssl_version: 'TLSv1_1' },
534
+ # }
535
+ #
536
+ # As you might guess, the above example also fails the connection
537
+ # if the client can't negotiate TLS v1.1.
538
+ # tls_options is ultimately passed to OpenSSL::SSL::SSLContext#set_params
539
+ # For more details, see
540
+ # http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
464
541
  #
465
542
  # Instantiating a Net::LDAP object does <i>not</i> result in network
466
543
  # traffic to the LDAP server. It simply stores the connection and binding
467
- # parameters in the object.
544
+ # parameters in the object. That's why Net::LDAP.new doesn't throw
545
+ # cert validation errors itself; #bind does instead.
468
546
  def initialize(args = {})
469
547
  @host = args[:host] || DefaultHost
470
548
  @port = args[:port] || DefaultPort
549
+ @hosts = args[:hosts]
471
550
  @verbose = false # Make this configurable with a switch on the class.
472
551
  @auth = args[:auth] || DefaultAuth
473
552
  @base = args[:base] || DefaultTreebase
474
553
  @force_no_page = args[:force_no_page] || DefaultForceNoPage
475
- encryption args[:encryption] # may be nil
554
+ @encryption = normalize_encryption(args[:encryption]) # may be nil
555
+ @connect_timeout = args[:connect_timeout]
476
556
 
477
557
  if pr = @auth[:password] and pr.respond_to?(:call)
478
558
  @auth[:password] = pr.call
@@ -523,7 +603,7 @@ class Net::LDAP
523
603
  @auth = {
524
604
  :method => :simple,
525
605
  :username => username,
526
- :password => password
606
+ :password => password,
527
607
  }
528
608
  end
529
609
  alias_method :auth, :authenticate
@@ -536,54 +616,12 @@ class Net::LDAP
536
616
  # additional capabilities are added, more configuration values will be
537
617
  # added here.
538
618
  #
539
- # The :simple_tls encryption method encrypts <i>all</i> communications
540
- # with the LDAP server. It completely establishes SSL/TLS encryption with
541
- # the LDAP server before any LDAP-protocol data is exchanged. There is no
542
- # plaintext negotiation and no special encryption-request controls are
543
- # sent to the server. <i>The :simple_tls option is the simplest, easiest
544
- # way to encrypt communications between Net::LDAP and LDAP servers.</i>
545
- # It's intended for cases where you have an implicit level of trust in the
546
- # authenticity of the LDAP server. No validation of the LDAP server's SSL
547
- # certificate is performed. This means that :simple_tls will not produce
548
- # errors if the LDAP server's encryption certificate is not signed by a
549
- # well-known Certification Authority. If you get communications or
550
- # protocol errors when using this option, check with your LDAP server
551
- # administrator. Pay particular attention to the TCP port you are
552
- # connecting to. It's impossible for an LDAP server to support plaintext
553
- # LDAP communications and <i>simple TLS</i> connections on the same port.
554
- # The standard TCP port for unencrypted LDAP connections is 389, but the
555
- # standard port for simple-TLS encrypted connections is 636. Be sure you
556
- # are using the correct port.
557
- #
558
- # The :start_tls like the :simple_tls encryption method also encrypts all
559
- # communcations with the LDAP server. With the exception that it operates
560
- # over the standard TCP port.
561
- #
562
- # In order to verify certificates and enable other TLS options, the
563
- # :tls_options hash can be passed alongside :simple_tls or :start_tls.
564
- # This hash contains any options that can be passed to
565
- # OpenSSL::SSL::SSLContext#set_params(). The most common options passed
566
- # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option,
567
- # which contains a path to a Certificate Authority file (PEM-encoded).
568
- #
569
- # Example for a default setup without custom settings:
570
- # {
571
- # :method => :simple_tls,
572
- # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
573
- # }
574
- #
575
- # Example for specifying a CA-File and only allowing TLSv1.1 connections:
619
+ # This method is deprecated.
576
620
  #
577
- # {
578
- # :method => :start_tls,
579
- # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" }
580
- # }
581
621
  def encryption(args)
582
- case args
583
- when :simple_tls, :start_tls
584
- args = { :method => args, :tls_options => {} }
585
- end
586
- @encryption = args
622
+ warn "Deprecation warning: please give :encryption option as a Hash to Net::LDAP.new"
623
+ return if args.nil?
624
+ @encryption = normalize_encryption(args)
587
625
  end
588
626
 
589
627
  # #open takes the same parameters as #new. #open makes a network
@@ -627,8 +665,11 @@ class Net::LDAP
627
665
  #++
628
666
  def get_operation_result
629
667
  result = @result
630
- result = result.result if result.is_a?(Net::LDAP::PDU)
631
668
  os = OpenStruct.new
669
+ if result.is_a?(Net::LDAP::PDU)
670
+ os.extended_response = result.extended_response
671
+ result = result.result
672
+ end
632
673
  if result.is_a?(Hash)
633
674
  # We might get a hash of LDAP response codes instead of a simple
634
675
  # numeric code.
@@ -740,10 +781,10 @@ class Net::LDAP
740
781
 
741
782
  instrument "search.net_ldap", args do |payload|
742
783
  @result = use_connection(args) do |conn|
743
- conn.search(args) { |entry|
784
+ conn.search(args) do |entry|
744
785
  result_set << entry if result_set
745
786
  yield entry if block_given?
746
- }
787
+ end
747
788
  end
748
789
 
749
790
  if return_result_set
@@ -882,7 +923,7 @@ class Net::LDAP
882
923
  # end
883
924
  def bind_as(args = {})
884
925
  result = false
885
- open { |me|
926
+ open do |me|
886
927
  rs = search args
887
928
  if rs and rs.first and dn = rs.first.dn
888
929
  password = args[:password]
@@ -890,7 +931,7 @@ class Net::LDAP
890
931
  result = rs if bind(:method => :simple, :username => dn,
891
932
  :password => password)
892
933
  end
893
- }
934
+ end
894
935
  result
895
936
  end
896
937
 
@@ -1017,6 +1058,44 @@ class Net::LDAP
1017
1058
  end
1018
1059
  end
1019
1060
 
1061
+ # Password Modify
1062
+ #
1063
+ # Change existing password:
1064
+ #
1065
+ # dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com'
1066
+ # auth = {
1067
+ # method: :simple,
1068
+ # username: dn,
1069
+ # password: 'passworD1'
1070
+ # }
1071
+ # ldap.password_modify(dn: dn,
1072
+ # auth: auth,
1073
+ # old_password: 'passworD1',
1074
+ # new_password: 'passworD2')
1075
+ #
1076
+ # Or get the LDAP server to generate a password for you:
1077
+ #
1078
+ # dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com'
1079
+ # auth = {
1080
+ # method: :simple,
1081
+ # username: dn,
1082
+ # password: 'passworD1'
1083
+ # }
1084
+ # ldap.password_modify(dn: dn,
1085
+ # auth: auth,
1086
+ # old_password: 'passworD1')
1087
+ #
1088
+ # ldap.get_operation_result.extended_response[0][0] #=> 'VtcgGf/G'
1089
+ #
1090
+ def password_modify(args)
1091
+ instrument "modify_password.net_ldap", args do |payload|
1092
+ @result = use_connection(args) do |conn|
1093
+ conn.password_modify(args)
1094
+ end
1095
+ @result.success?
1096
+ end
1097
+ end
1098
+
1020
1099
  # Add a value to an attribute. Takes the full DN of the entry to modify,
1021
1100
  # the name (Symbol or String) of the attribute, and the value (String or
1022
1101
  # Array). If the attribute does not exist (and there are no schema
@@ -1135,7 +1214,7 @@ class Net::LDAP
1135
1214
  :supportedExtension,
1136
1215
  :supportedFeatures,
1137
1216
  :supportedLdapVersion,
1138
- :supportedSASLMechanisms
1217
+ :supportedSASLMechanisms,
1139
1218
  ])
1140
1219
  (rs and rs.first) or Net::LDAP::Entry.new
1141
1220
  end
@@ -1195,6 +1274,18 @@ class Net::LDAP
1195
1274
  @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS)
1196
1275
  end
1197
1276
 
1277
+ # Mask auth password
1278
+ def inspect
1279
+ inspected = super
1280
+ inspected.gsub! @auth[:password], "*******" if @auth[:password]
1281
+ inspected
1282
+ end
1283
+
1284
+ # Internal: Set @open_connection for testing
1285
+ def connection=(connection)
1286
+ @open_connection = connection
1287
+ end
1288
+
1198
1289
  private
1199
1290
 
1200
1291
  # Yields an open connection if there is one, otherwise establishes a new
@@ -1207,11 +1298,9 @@ class Net::LDAP
1207
1298
  else
1208
1299
  begin
1209
1300
  conn = new_connection
1210
- if (result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
1211
- yield conn
1212
- else
1213
- return result
1214
- end
1301
+ result = conn.bind(args[:auth] || @auth)
1302
+ return result unless result.result_code == Net::LDAP::ResultCodeSuccess
1303
+ yield conn
1215
1304
  ensure
1216
1305
  conn.close if conn
1217
1306
  end
@@ -1220,10 +1309,35 @@ class Net::LDAP
1220
1309
 
1221
1310
  # Establish a new connection to the LDAP server
1222
1311
  def new_connection
1223
- Net::LDAP::Connection.new \
1312
+ connection = Net::LDAP::Connection.new \
1224
1313
  :host => @host,
1225
1314
  :port => @port,
1315
+ :hosts => @hosts,
1226
1316
  :encryption => @encryption,
1227
- :instrumentation_service => @instrumentation_service
1317
+ :instrumentation_service => @instrumentation_service,
1318
+ :connect_timeout => @connect_timeout
1319
+
1320
+ # Force connect to see if there's a connection error
1321
+ connection.socket
1322
+ connection
1323
+ rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, Net::LDAP::ConnectionRefusedError => e
1324
+ @result = {
1325
+ :resultCode => 52,
1326
+ :errorMessage => ResultStrings[ResultCodeUnavailable],
1327
+ }
1328
+ raise e
1329
+ end
1330
+
1331
+ # Normalize encryption parameter the constructor accepts, expands a few
1332
+ # convenience symbols into recognizable hashes
1333
+ def normalize_encryption(args)
1334
+ return if args.nil?
1335
+ return args if args.is_a? Hash
1336
+
1337
+ case method = args.to_sym
1338
+ when :simple_tls, :start_tls
1339
+ { :method => method, :tls_options => {} }
1340
+ end
1228
1341
  end
1342
+
1229
1343
  end # class LDAP
data/lib/net/snmp.rb CHANGED
@@ -12,7 +12,7 @@ module Net
12
12
  2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2)
13
13
  3 => :integer # TimeTicks32, (RFC2578 sec 2)
14
14
  },
15
- :constructed => {}
15
+ :constructed => {},
16
16
  },
17
17
  :context_specific => {
18
18
  :primitive => {},
@@ -20,8 +20,8 @@ module Net
20
20
  0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2)
21
21
  1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3)
22
22
  2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4)
23
- }
24
- }
23
+ },
24
+ },
25
25
  })
26
26
 
27
27
  # SNMP 32-bit counter.
@@ -70,7 +70,7 @@ module Net
70
70
  :get_next_request,
71
71
  :get_response,
72
72
  :set_request,
73
- :trap
73
+ :trap,
74
74
  ]
75
75
  ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1
76
76
  0 => "noError",
@@ -78,7 +78,7 @@ module Net
78
78
  2 => "noSuchName",
79
79
  3 => "badValue",
80
80
  4 => "readOnly",
81
- 5 => "genErr"
81
+ 5 => "genErr",
82
82
  }
83
83
 
84
84
  class << self
@@ -148,7 +148,7 @@ module Net
148
148
  # data[2] is error_index, always zero.
149
149
  send :error_status=, 0
150
150
  send :error_index=, 0
151
- data[3].each do |n,v|
151
+ data[3].each do |n, v|
152
152
  # A variable-binding, of which there may be several,
153
153
  # consists of an OID and a BER null.
154
154
  # We're ignoring the null, we might want to verify it instead.
@@ -166,7 +166,7 @@ module Net
166
166
  send :request_id=, data[0].to_i
167
167
  send :error_status=, data[1].to_i
168
168
  send :error_index=, data[2].to_i
169
- data[3].each do |n,v|
169
+ data[3].each do |n, v|
170
170
  # A variable-binding, of which there may be several,
171
171
  # consists of an OID and a BER null.
172
172
  # We're ignoring the null, we might want to verify it instead.
@@ -177,7 +177,7 @@ module Net
177
177
 
178
178
 
179
179
  def version= ver
180
- unless [0,2].include?(ver)
180
+ unless [0, 2].include?(ver)
181
181
  raise Error.new("unknown snmp-version: #{ver}")
182
182
  end
183
183
  @version = ver
@@ -191,7 +191,7 @@ module Net
191
191
  end
192
192
 
193
193
  def error_status= es
194
- unless ErrorStatusCodes.has_key?(es)
194
+ unless ErrorStatusCodes.key?(es)
195
195
  raise Error.new("unknown error-status: #{es}")
196
196
  end
197
197
  @error_status = es
@@ -227,10 +227,10 @@ module Net
227
227
  error_status.to_ber,
228
228
  error_index.to_ber,
229
229
  [
230
- @variables.map {|n,v|
230
+ @variables.map do|n, v|
231
231
  [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
232
- }
233
- ].to_ber_sequence
232
+ end,
233
+ ].to_ber_sequence,
234
234
  ].to_ber_contextspecific(0)
235
235
  when :get_next_request
236
236
  [
@@ -238,10 +238,10 @@ module Net
238
238
  error_status.to_ber,
239
239
  error_index.to_ber,
240
240
  [
241
- @variables.map {|n,v|
241
+ @variables.map do|n, v|
242
242
  [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
243
- }
244
- ].to_ber_sequence
243
+ end,
244
+ ].to_ber_sequence,
245
245
  ].to_ber_contextspecific(1)
246
246
  when :get_response
247
247
  [
@@ -249,10 +249,10 @@ module Net
249
249
  error_status.to_ber,
250
250
  error_index.to_ber,
251
251
  [
252
- @variables.map {|n,v|
252
+ @variables.map do|n, v|
253
253
  [n.to_ber_oid, v.to_ber].to_ber_sequence
254
- }
255
- ].to_ber_sequence
254
+ end,
255
+ ].to_ber_sequence,
256
256
  ].to_ber_contextspecific(2)
257
257
  else
258
258
  raise Error.new( "unknown pdu-type: #{pdu_type}" )
data/net-ldap.gemspec CHANGED
@@ -26,10 +26,12 @@ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).}
26
26
  s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap}
27
27
  s.rdoc_options = ["--main", "README.rdoc"]
28
28
  s.require_paths = ["lib"]
29
- s.required_ruby_version = ">= 1.9.3"
29
+ s.required_ruby_version = ">= 2.0.0"
30
30
  s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services}
31
31
 
32
32
  s.add_development_dependency("flexmock", "~> 1.3")
33
33
  s.add_development_dependency("rake", "~> 10.0")
34
- s.add_development_dependency("rubocop", "~> 0.28.0")
34
+ s.add_development_dependency("rubocop", "~> 0.42.0")
35
+ s.add_development_dependency("test-unit")
36
+ s.add_development_dependency("byebug")
35
37
  end
data/script/changelog ADDED
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # Usage: script/changelog [-r <repo>] [-b <base>] [-h <head>]
3
+ #
4
+ # repo: BASE string of GitHub REPOsitory url. e.g. "user_or_org/REPOsitory". Defaults to git remote url.
5
+ # base: git ref to compare from. e.g. "v1.3.1". Defaults to latest git tag.
6
+ # head: git ref to compare to. Defaults to "HEAD".
7
+ #
8
+ # Generate a changelog preview from pull requests merged between `base` and
9
+ # `head`.
10
+ #
11
+ # https://github.com/jch/release-scripts/blob/master/changelog
12
+ set -e
13
+
14
+ [ $# -eq 0 ] && set -- --help
15
+ while [[ $# > 1 ]]
16
+ do
17
+ key="$1"
18
+ case $key in
19
+ -r|--repo)
20
+ repo="$2"
21
+ shift
22
+ ;;
23
+ -b|--base)
24
+ base="$2"
25
+ shift
26
+ ;;
27
+ -h|--head)
28
+ head="$2"
29
+ shift
30
+ ;;
31
+ *)
32
+ ;;
33
+ esac
34
+ shift
35
+ done
36
+
37
+ repo="${repo:-$(git remote -v | grep push | awk '{print $2}' | cut -d'/' -f4- | sed 's/\.git//')}"
38
+ base="${base:-$(git tag -l | sort -t. -k 1,1n -k 2,2n -k 3,3n | tail -n 1)}"
39
+ head="${head:-HEAD}"
40
+ api_url="https://api.github.com"
41
+
42
+ # get merged PR's. Better way is to query the API for these, but this is easier
43
+ for pr in $(git log --oneline $base..$head | grep "Merge pull request" | awk '{gsub("#",""); print $5}')
44
+ do
45
+ # frustrated with trying to pull out the right values, fell back to ruby
46
+ curl -s "$api_url/repos/$repo/pulls/$pr" | ruby -rjson -e 'pr=JSON.parse(STDIN.read); puts "* #{pr[%q(title)]} {##{pr[%q(number)]}}[#{pr[%q(html_url)]}]"'
47
+ done