ruby-net-ldap 0.0.2 → 0.0.3
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.
- data/ChangeLog +4 -0
- data/lib/net/ber.rb +17 -1
- data/lib/net/ldap.rb +104 -10
- metadata +2 -2
data/ChangeLog
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
= Net::LDAP Changelog
|
2
2
|
|
3
|
+
== Net::LDAP 0.0.3: July 26, 2006
|
4
|
+
* Added simple TLS encryption.
|
5
|
+
Thanks to Garett Shulman for suggestions and for helping test.
|
6
|
+
|
3
7
|
== Net::LDAP 0.0.2: July 12, 2006
|
4
8
|
* Fixed malformation in distro tarball and gem.
|
5
9
|
* Improved documentation.
|
data/lib/net/ber.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: ber.rb
|
1
|
+
# $Id: ber.rb 142 2006-07-26 12:20:33Z blackhedd $
|
2
2
|
#
|
3
3
|
# NET::BER
|
4
4
|
# Mixes ASN.1/BER convenience methods into several standard classes.
|
@@ -139,6 +139,22 @@ class StringIO
|
|
139
139
|
include Net::BER::BERParser
|
140
140
|
end
|
141
141
|
|
142
|
+
begin
|
143
|
+
require 'openssl'
|
144
|
+
class OpenSSL::SSL::SSLSocket
|
145
|
+
include Net::BER::BERParser
|
146
|
+
end
|
147
|
+
rescue LoadError
|
148
|
+
# Ignore LoadError.
|
149
|
+
# DON'T ignore NameError, which means the SSLSocket class
|
150
|
+
# is somehow unavailable on this implementation of Ruby's openssl.
|
151
|
+
# This may be WRONG, however, because we don't yet know how Ruby's
|
152
|
+
# openssl behaves on machines with no OpenSSL library. I suppose
|
153
|
+
# it's possible they do not fail to require 'openssl' but do not
|
154
|
+
# create the classes. So this code is provisional.
|
155
|
+
# Also, you might think that OpenSSL::SSL::SSLSocket inherits from
|
156
|
+
# IO so we'd pick it up above. But you'd be wrong.
|
157
|
+
end
|
142
158
|
|
143
159
|
class String
|
144
160
|
def read_ber syntax=nil
|
data/lib/net/ldap.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: ldap.rb
|
1
|
+
# $Id: ldap.rb 144 2006-07-26 21:35:38Z blackhedd $
|
2
2
|
#
|
3
3
|
# Net::LDAP for Ruby
|
4
4
|
#
|
@@ -18,6 +18,13 @@
|
|
18
18
|
|
19
19
|
require 'socket'
|
20
20
|
require 'ostruct'
|
21
|
+
|
22
|
+
begin
|
23
|
+
require 'openssl'
|
24
|
+
$net_ldap_openssl_available = true
|
25
|
+
rescue LoadError
|
26
|
+
end
|
27
|
+
|
21
28
|
require 'net/ber'
|
22
29
|
require 'net/ldap/pdu'
|
23
30
|
require 'net/ldap/filter'
|
@@ -256,7 +263,7 @@ module Net
|
|
256
263
|
|
257
264
|
class LdapError < Exception; end
|
258
265
|
|
259
|
-
VERSION = "0.0.
|
266
|
+
VERSION = "0.0.3"
|
260
267
|
|
261
268
|
|
262
269
|
SearchScope_BaseObject = 0
|
@@ -348,7 +355,7 @@ module Net
|
|
348
355
|
|
349
356
|
|
350
357
|
# Instantiate an object of type Net::LDAP to perform directory operations.
|
351
|
-
# This constructor takes a Hash containing arguments. The following arguments
|
358
|
+
# This constructor takes a Hash containing arguments, all of which are either optional or may be specified later with other methods as described below. The following arguments
|
352
359
|
# are supported:
|
353
360
|
# * :host => the LDAP server's IP-address (default 127.0.0.1)
|
354
361
|
# * :port => the LDAP server's TCP port (default 389)
|
@@ -356,6 +363,8 @@ module Net
|
|
356
363
|
# {:method => :anonymous} and
|
357
364
|
# {:method => :simple, :username => your_user_name, :password => your_password }
|
358
365
|
# The password parameter may be a Proc that returns a String.
|
366
|
+
# * :base => a default treebase parameter for searches performed against the LDAP server. If you don't give this value, then each call to #search must specify a treebase parameter. If you do give this value, then it will be used in subsequent calls to #search that do not specify a treebase. If you give a treebase value in any particular call to #search, that value will override any treebase value you give here.
|
367
|
+
# * :encryption => specifies the encryption to be used in communicating with the LDAP server. The value is either a Hash containing additional parameters, or the Symbol :simple_tls, which is equivalent to specifying the Hash {:method => :simple_tls}. There is a fairly large range of potential values that may be given for this parameter. See #encryption for details.
|
359
368
|
#
|
360
369
|
# Instantiating a Net::LDAP object does <i>not</i> result in network traffic to
|
361
370
|
# the LDAP server. It simply stores the connection and binding parameters in the
|
@@ -367,6 +376,7 @@ module Net
|
|
367
376
|
@verbose = false # Make this configurable with a switch on the class.
|
368
377
|
@auth = args[:auth] || DefaultAuth
|
369
378
|
@base = args[:base] || DefaultTreebase
|
379
|
+
encryption args[:encryption] # may be nil
|
370
380
|
|
371
381
|
if pr = @auth[:password] and pr.respond_to?(:call)
|
372
382
|
@auth[:password] = pr.call
|
@@ -417,6 +427,51 @@ module Net
|
|
417
427
|
|
418
428
|
alias_method :auth, :authenticate
|
419
429
|
|
430
|
+
# Convenience method to specify encryption characteristics for connections
|
431
|
+
# to LDAP servers. Called implicitly by #new and #open, but may also be called
|
432
|
+
# by user code if desired.
|
433
|
+
# The single argument is generally a Hash (but see below for convenience alternatives).
|
434
|
+
# This implementation is currently a stub, supporting only a few encryption
|
435
|
+
# alternatives. As additional capabilities are added, more configuration values
|
436
|
+
# will be added here.
|
437
|
+
#
|
438
|
+
# Currently, the only supported argument is {:method => :simple_tls}.
|
439
|
+
# (Equivalently, you may pass the symbol :simple_tls all by itself, without
|
440
|
+
# enclosing it in a Hash.)
|
441
|
+
#
|
442
|
+
# The :simple_tls encryption method encrypts <i>all</i> communications with the LDAP
|
443
|
+
# server.
|
444
|
+
# It completely establishes SSL/TLS encryption with the LDAP server
|
445
|
+
# before any LDAP-protocol data is exchanged.
|
446
|
+
# There is no plaintext negotiation and no special encryption-request controls
|
447
|
+
# are sent to the server.
|
448
|
+
# <i>The :simple_tls option is the simplest, easiest way to encrypt communications
|
449
|
+
# between Net::LDAP and LDAP servers.</i>
|
450
|
+
# It's intended for cases where you have an implicit level of trust in the authenticity
|
451
|
+
# of the LDAP server. No validation of the LDAP server's SSL certificate is
|
452
|
+
# performed. This means that :simple_tls will not produce errors if the LDAP
|
453
|
+
# server's encryption certificate is not signed by a well-known Certification
|
454
|
+
# Authority.
|
455
|
+
# If you get communications or protocol errors when using this option, check
|
456
|
+
# with your LDAP server administrator. Pay particular attention to the TCP port
|
457
|
+
# you are connecting to. It's impossible for an LDAP server to support plaintext
|
458
|
+
# LDAP communications and <i>simple TLS</i> connections on the same port.
|
459
|
+
# The standard TCP port for unencrypted LDAP connections is 389, but the standard
|
460
|
+
# port for simple-TLS encrypted connections is 636. Be sure you are using the
|
461
|
+
# correct port.
|
462
|
+
#
|
463
|
+
# <i>[Note: a future version of Net::LDAP will support the STARTTLS LDAP control,
|
464
|
+
# which will enable encrypted communications on the same TCP port used for
|
465
|
+
# unencrypted connections.]</i>
|
466
|
+
#
|
467
|
+
def encryption args
|
468
|
+
if args == :simple_tls
|
469
|
+
args = {:method => :simple_tls}
|
470
|
+
end
|
471
|
+
@encryption = args
|
472
|
+
end
|
473
|
+
|
474
|
+
|
420
475
|
# #open takes the same parameters as #new. #open makes a network connection to the
|
421
476
|
# LDAP server and then passes a newly-created Net::LDAP object to the caller-supplied block.
|
422
477
|
# Within the block, you can call any of the instance methods of Net::LDAP to
|
@@ -484,7 +539,7 @@ module Net
|
|
484
539
|
# if the bind was unsuccessful.
|
485
540
|
def open
|
486
541
|
raise LdapError.new( "open already in progress" ) if @open_connection
|
487
|
-
@open_connection = Connection.new( :host => @host, :port => @port )
|
542
|
+
@open_connection = Connection.new( :host => @host, :port => @port, :encryption => @encryption )
|
488
543
|
@open_connection.bind @auth
|
489
544
|
yield self
|
490
545
|
@open_connection.close
|
@@ -579,7 +634,7 @@ module Net
|
|
579
634
|
}
|
580
635
|
else
|
581
636
|
@result = 0
|
582
|
-
conn = Connection.new( :host => @host, :port => @port )
|
637
|
+
conn = Connection.new( :host => @host, :port => @port, :encryption => @encryption )
|
583
638
|
if (@result = conn.bind( args[:auth] || @auth )) == 0
|
584
639
|
@result = conn.search( args ) {|entry|
|
585
640
|
result_set << entry if result_set
|
@@ -641,7 +696,7 @@ module Net
|
|
641
696
|
if @open_connection
|
642
697
|
@result = @open_connection.bind @auth
|
643
698
|
else
|
644
|
-
conn = Connection.new( :host => @host, :port => @port )
|
699
|
+
conn = Connection.new( :host => @host, :port => @port , :encryption => @encryption)
|
645
700
|
@result = conn.bind @auth
|
646
701
|
conn.close
|
647
702
|
end
|
@@ -692,7 +747,7 @@ module Net
|
|
692
747
|
@result = @open_connection.add( args )
|
693
748
|
else
|
694
749
|
@result = 0
|
695
|
-
conn = Connection.new( :host => @host, :port => @port )
|
750
|
+
conn = Connection.new( :host => @host, :port => @port, :encryption => @encryption)
|
696
751
|
if (@result = conn.bind( args[:auth] || @auth )) == 0
|
697
752
|
@result = conn.add( args )
|
698
753
|
end
|
@@ -776,7 +831,7 @@ module Net
|
|
776
831
|
@result = @open_connection.modify( args )
|
777
832
|
else
|
778
833
|
@result = 0
|
779
|
-
conn = Connection.new( :host => @host, :port => @port )
|
834
|
+
conn = Connection.new( :host => @host, :port => @port, :encryption => @encryption )
|
780
835
|
if (@result = conn.bind( args[:auth] || @auth )) == 0
|
781
836
|
@result = conn.modify( args )
|
782
837
|
end
|
@@ -848,7 +903,7 @@ module Net
|
|
848
903
|
@result = @open_connection.rename( args )
|
849
904
|
else
|
850
905
|
@result = 0
|
851
|
-
conn = Connection.new( :host => @host, :port => @port )
|
906
|
+
conn = Connection.new( :host => @host, :port => @port, :encryption => @encryption )
|
852
907
|
if (@result = conn.bind( args[:auth] || @auth )) == 0
|
853
908
|
@result = conn.rename( args )
|
854
909
|
end
|
@@ -878,7 +933,7 @@ module Net
|
|
878
933
|
@result = @open_connection.delete( args )
|
879
934
|
else
|
880
935
|
@result = 0
|
881
|
-
conn = Connection.new( :host => @host, :port => @port )
|
936
|
+
conn = Connection.new( :host => @host, :port => @port, :encryption => @encryption )
|
882
937
|
if (@result = conn.bind( args[:auth] || @auth )) == 0
|
883
938
|
@result = conn.delete( args )
|
884
939
|
end
|
@@ -908,10 +963,49 @@ module Net
|
|
908
963
|
raise LdapError.new( "no connection to server" )
|
909
964
|
end
|
910
965
|
|
966
|
+
if server[:encryption]
|
967
|
+
setup_encryption server[:encryption]
|
968
|
+
end
|
969
|
+
|
911
970
|
yield self if block_given?
|
912
971
|
end
|
913
972
|
|
914
973
|
|
974
|
+
#--
|
975
|
+
# Helper method called only from new, and only after we have a successfully-opened
|
976
|
+
# @conn instance variable, which is a TCP connection.
|
977
|
+
# Depending on the received arguments, we establish SSL, potentially replacing
|
978
|
+
# the value of @conn accordingly.
|
979
|
+
# Don't generate any errors here if no encryption is requested.
|
980
|
+
# DO raise LdapError objects if encryption is requested and we have trouble setting
|
981
|
+
# it up. That includes if OpenSSL is not set up on the machine. (Question:
|
982
|
+
# how does the Ruby OpenSSL wrapper react in that case?)
|
983
|
+
# DO NOT filter exceptions raised by the OpenSSL library. Let them pass back
|
984
|
+
# to the user. That should make it easier for us to debug the problem reports.
|
985
|
+
# Presumably (hopefully?) that will also produce recognizable errors if someone
|
986
|
+
# tries to use this on a machine without OpenSSL.
|
987
|
+
#
|
988
|
+
# The simple_tls method is intended as the simplest, stupidest, easiest solution
|
989
|
+
# for people who want nothing more than encrypted comms with the LDAP server.
|
990
|
+
# It doesn't do any server-cert validation and requires nothing in the way
|
991
|
+
# of key files and root-cert files, etc etc.
|
992
|
+
# OBSERVE: WE REPLACE the value of @conn, which is presumed to be a connected
|
993
|
+
# TCPsocket object.
|
994
|
+
#
|
995
|
+
def setup_encryption args
|
996
|
+
case args[:method]
|
997
|
+
when :simple_tls
|
998
|
+
raise LdapError.new("openssl unavailable") unless $net_ldap_openssl_available
|
999
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
1000
|
+
@conn = OpenSSL::SSL::SSLSocket.new(@conn, ctx)
|
1001
|
+
@conn.connect
|
1002
|
+
@conn.sync_close = true
|
1003
|
+
# additional branches requiring server validation and peer certs, etc. go here.
|
1004
|
+
else
|
1005
|
+
raise LdapError.new( "unsupported encryption method #{args[:method]}" )
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
|
915
1009
|
#--
|
916
1010
|
# close
|
917
1011
|
# This is provided as a convenience method to make
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-net-ldap
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2006-07-
|
6
|
+
version: 0.0.3
|
7
|
+
date: 2006-07-27 00:00:00 -04:00
|
8
8
|
summary: A pure Ruby LDAP client library.
|
9
9
|
require_paths:
|
10
10
|
- lib
|