net-ldap 0.11 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.

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