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.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +471 -180
- data/.travis.yml +10 -5
- data/Contributors.rdoc +1 -0
- data/History.rdoc +60 -0
- data/README.rdoc +18 -11
- data/Rakefile +0 -1
- data/lib/net/ber/ber_parser.rb +4 -4
- data/lib/net/ber/core_ext/array.rb +1 -1
- data/lib/net/ber/core_ext/integer.rb +1 -1
- data/lib/net/ber/core_ext/string.rb +1 -1
- data/lib/net/ber.rb +37 -5
- data/lib/net/ldap/auth_adapter/gss_spnego.rb +41 -0
- data/lib/net/ldap/auth_adapter/sasl.rb +62 -0
- data/lib/net/ldap/auth_adapter/simple.rb +34 -0
- data/lib/net/ldap/auth_adapter.rb +29 -0
- data/lib/net/ldap/connection.rb +197 -187
- data/lib/net/ldap/dataset.rb +2 -2
- data/lib/net/ldap/dn.rb +4 -5
- data/lib/net/ldap/entry.rb +4 -5
- data/lib/net/ldap/error.rb +36 -1
- data/lib/net/ldap/filter.rb +6 -6
- data/lib/net/ldap/pdu.rb +26 -2
- data/lib/net/ldap/version.rb +1 -1
- data/lib/net/ldap.rb +189 -75
- data/lib/net/snmp.rb +18 -18
- data/net-ldap.gemspec +4 -2
- data/script/changelog +47 -0
- data/script/generate-fixture-ca +48 -0
- data/script/install-openldap +67 -44
- data/test/ber/core_ext/test_array.rb +1 -1
- data/test/ber/test_ber.rb +11 -3
- data/test/fixtures/ca/ca.info +4 -0
- data/test/fixtures/ca/cacert.pem +24 -0
- data/test/fixtures/ca/cakey.pem +190 -0
- data/test/fixtures/openldap/slapd.conf.ldif +1 -1
- data/test/integration/test_add.rb +1 -1
- data/test/integration/test_ber.rb +1 -1
- data/test/integration/test_bind.rb +220 -10
- data/test/integration/test_delete.rb +1 -1
- data/test/integration/test_open.rb +1 -1
- data/test/integration/test_password_modify.rb +80 -0
- data/test/integration/test_search.rb +1 -1
- data/test/support/vm/openldap/README.md +35 -3
- data/test/support/vm/openldap/Vagrantfile +1 -0
- data/test/test_auth_adapter.rb +15 -0
- data/test/test_dn.rb +3 -3
- data/test/test_filter.rb +4 -4
- data/test/test_filter_parser.rb +4 -0
- data/test/test_helper.rb +10 -2
- data/test/test_ldap.rb +64 -10
- data/test/test_ldap_connection.rb +115 -28
- data/test/test_ldif.rb +11 -11
- data/test/test_search.rb +2 -2
- data/test/test_snmp.rb +4 -4
- data/testserver/ldapserver.rb +11 -12
- metadata +50 -8
- 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
|
-
|
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.
|
data/lib/net/ldap/version.rb
CHANGED
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 = [
|
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 = [
|
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 =
|
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
|
-
#
|
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
|
-
|
583
|
-
|
584
|
-
|
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)
|
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
|
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
|
-
|
1211
|
-
|
1212
|
-
|
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.
|
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
|
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
|
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
|
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 = ">=
|
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.
|
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
|