diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 7b82b48c..7202fe7a 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -1240,7 +1240,7 @@ def initialize(host, port: nil, ssl: nil, response_handlers: nil, @greeting = nil @capabilities = nil @enabled = Set.new - @tls_verified = false + @tls_connected = @tls_verified = false @connection_state = ConnectionState::NotAuthenticated.new # Client Protocol Receiver @@ -1302,7 +1302,7 @@ def inspect if tls_verified? "TLS" elsif ssl_ctx && @sock.kind_of?(OpenSSL::SSL::SSLSocket) - "TLS (#{@sock.session ? "NOT VERIFIED" : "NOT ESTABLISHED"})" + "TLS (#{@tls_connected ? "NOT VERIFIED" : "NOT ESTABLISHED"})" else "PLAINTEXT#{" (TLS NOT STARTED)" if ssl_ctx}" end @@ -4129,6 +4129,7 @@ def start_tls_session @sock.sync_close = true @sock.hostname = @host if @sock.respond_to? :hostname= ssl_socket_connect(@sock, open_timeout) + @tls_connected = true if ssl_ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE @sock.post_connection_check(@host) @tls_verified = true diff --git a/test/net/imap/test_imap_tls.rb b/test/net/imap/test_imap_tls.rb index 0fbceed8..b79ba930 100644 --- a/test/net/imap/test_imap_tls.rb +++ b/test/net/imap/test_imap_tls.rb @@ -30,6 +30,30 @@ def test_imaps_unknown_ca end end + def assert_tls_unstarted(imap) = assert_tls_stage imap, :unstarted + def assert_tls_incomplete(imap) = assert_tls_stage imap, :incomplete + def assert_tls_unverified(imap) = assert_tls_stage imap, :unverified + def assert_tls_verified(imap) = assert_tls_stage imap, :verified + + INSPECT_INCLUDES = { + unstarted: " PLAINTEXT (TLS NOT STARTED) disconnected", + incomplete: " TLS (NOT ESTABLISHED) disconnected", + unverified: " TLS (NOT VERIFIED) disconnected", + verified: " TLS disconnected", + } + + def assert_tls_stage(imap, stage) + verified = stage == :verified + assert imap.ssl_ctx_params.frozen?, "#ssl_ctx_params should be frozen" + assert_kind_of Hash, imap.ssl_ctx_params, + "#ssl_ctx_params should be a Hash" + assert_kind_of OpenSSL::SSL::SSLContext, imap.ssl_ctx, + "#ssl_ctx should be an OpenSSL::SSL::SSLContext" + assert_equal verified, imap.tls_verified?, + "#tls_verified? should be #{verified}" + assert_include imap.inspect, INSPECT_INCLUDES.fetch(stage) + end + def test_imaps_with_ca_file # Assert verified *after* the imaps_test and assert_nothing_raised blocks. # Otherwise, failures can't logout and need to wait for the timeout. @@ -50,7 +74,7 @@ def test_imaps_with_ca_file end end assert_equal true, verified - assert_equal true, imap.tls_verified? + assert_tls_verified imap assert_equal({ca_file: CA_FILE}, imap.ssl_ctx_params) assert_equal(CA_FILE, imap.ssl_ctx.ca_file) assert_equal(OpenSSL::SSL::VERIFY_PEER, imap.ssl_ctx.verify_mode) @@ -77,7 +101,7 @@ def test_imaps_verify_none end end assert_equal false, verified - assert_equal false, imap.tls_verified? + assert_tls_unverified imap assert_equal({verify_mode: OpenSSL::SSL::VERIFY_NONE}, imap.ssl_ctx_params) assert_equal(nil, imap.ssl_ctx.ca_file) @@ -111,7 +135,7 @@ def test_starttls_unknown_ca end assert_kind_of(OpenSSL::SSL::SSLError, ex) assert_local_backtrace ex - assert_equal false, imap.tls_verified? + assert_tls_incomplete imap assert_equal({}, imap.ssl_ctx_params) assert_equal(nil, imap.ssl_ctx.ca_file) assert_equal(OpenSSL::SSL::VERIFY_PEER, imap.ssl_ctx.verify_mode) @@ -131,8 +155,7 @@ def test_starttls assert_equal false, initial_verified assert_equal false, initial_params assert_equal nil, initial_ctx - assert_equal true, imap.tls_verified? - assert_include imap.inspect, " TLS disconnected" + assert_tls_verified imap assert_equal({ca_file: CA_FILE}, imap.ssl_ctx_params) rescue SystemCallError skip $! @@ -167,8 +190,7 @@ def test_starttls_stripping_not_ok imap.disconnect if imap && !imap.disconnected? end - assert_equal false, imap.tls_verified? - assert_include imap.inspect, " PLAINTEXT (TLS NOT STARTED) " + assert_tls_unstarted imap assert_equal({ca_file: CA_FILE}, imap.ssl_ctx_params) assert_equal(CA_FILE, imap.ssl_ctx.ca_file) assert_equal(OpenSSL::SSL::VERIFY_PEER, imap.ssl_ctx.verify_mode) @@ -214,8 +236,7 @@ def test_starttls_stripping_ok_sent_before_response ensure imap.disconnect if imap && !imap.disconnected? end - assert_equal false, imap.tls_verified? - assert_include imap.inspect, " PLAINTEXT (TLS NOT STARTED) " + assert_tls_unstarted imap assert_equal({ca_file: CA_FILE}, imap.ssl_ctx_params) assert_equal(CA_FILE, imap.ssl_ctx.ca_file) assert_equal(OpenSSL::SSL::VERIFY_PEER, imap.ssl_ctx.verify_mode)