diff --git a/ChangeLog b/ChangeLog index 949e636..bdc0168 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,8 @@ * Added some support for SNMP data-handling. * Extended support for server-reported error messages. This was provisionally added to Net::LDAP#add, and eventually will be added to other methods. +* Belatedly added a patch contributed by Kouhei Sutou last October. + The patch adds start_tls support. == Net::LDAP 0.0.4: August 15, 2006 diff --git a/lib/net/ber.rb b/lib/net/ber.rb index 6a15224..0b40d1f 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -124,6 +124,11 @@ module Net :constructed => { 16 => :array, 17 => :array + }, + :context_specific => { + :primitive => { + 10 => :integer + } } } }) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index fe40ec9..e4fec28 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -321,6 +321,7 @@ module Net DefaultAuth = {:method => :anonymous} DefaultTreebase = "dc=com" + StartTlsOid = "1.3.6.1.4.1.1466.20037" ResultStrings = { 0 => "Success", @@ -473,8 +474,9 @@ module Net # unencrypted connections.] # def encryption args - if args == :simple_tls - args = {:method => :simple_tls} + case args + when :simple_tls, :start_tls + args = {:method => args} end @encryption = args end @@ -1114,6 +1116,11 @@ module Net # OBSERVE: WE REPLACE the value of @conn, which is presumed to be a connected # TCPsocket object. # + # The start_tls method is supported by many servers over the standard LDAP port. + # It does not require an alternative port for encrypted communications, as with + # simple_tls. + # Thanks for Kouhei Sutou for generously contributing the :start_tls path. + # def setup_encryption args case args[:method] when :simple_tls @@ -1123,6 +1130,24 @@ module Net @conn.connect @conn.sync_close = true # additional branches requiring server validation and peer certs, etc. go here. + when :start_tls + raise LdapError.new("openssl unavailable") unless $net_ldap_openssl_available + msgid = next_msgid.to_ber + request = [StartTlsOid.to_ber].to_ber_appsequence( Net::LdapPdu::ExtendedRequest ) + request_pkt = [msgid, request].to_ber_sequence + @conn.write request_pkt + be = @conn.read_ber(AsnSyntax) + raise LdapError.new("no start_tls result") if be.nil? + pdu = Net::LdapPdu.new(be) + raise LdapError.new("no start_tls result") if pdu.nil? + if pdu.result_code.zero? + ctx = OpenSSL::SSL::SSLContext.new + @conn = OpenSSL::SSL::SSLSocket.new(@conn, ctx) + @conn.connect + @conn.sync_close = true + else + raise LdapError.new("start_tls failed: #{pdu.result_code}") + end else raise LdapError.new( "unsupported encryption method #{args[:method]}" ) end diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 0dbe56c..585b28c 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -47,6 +47,8 @@ class LdapPdu DeleteResponse = 11 ModifyRDNResponse = 13 SearchResultReferral = 19 + ExtendedRequest = 23 + ExtendedResponse = 24 attr_reader :msg_id, :app_tag attr_reader :search_dn, :search_attributes, :search_entry @@ -114,6 +116,8 @@ class LdapPdu parse_bind_request ber_object[1] when UnbindRequest parse_unbind_request ber_object[1] + when ExtendedResponse + parse_ldap_result ber_object[1] else raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" ) end