Skip to content

Commit 4520aa8

Browse files
committed
🔒 Add Net::IMAP#tls_verified?
Returns true after the TLS negotiation has completed _and_ the remote hostname has been verified. This can be used, for example, by automated safeguards against selecting particular SASL mechanisms—or against authenticating at all—when TLS hasn't been established _and_ verified the peer.
1 parent ab05234 commit 4520aa8

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

lib/net/imap.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,11 @@ class IMAP < Protocol
696696
# The port this client connected to
697697
attr_reader :port
698698

699+
# Returns true after the TLS negotiation has completed and the remote
700+
# hostname has been verified. Returns false when TLS has been established
701+
# but peer verification was disabled.
702+
def tls_verified?; @tls_verified end
703+
699704
# Returns the debug mode.
700705
def self.debug
701706
return @@debug
@@ -2261,6 +2266,7 @@ def initialize(host, port_or_options = {},
22612266
@utf8_strings = false
22622267
@open_timeout = options[:open_timeout] || 30
22632268
@idle_response_timeout = options[:idle_response_timeout] || 5
2269+
@tls_verified = false
22642270
@parser = ResponseParser.new
22652271
@sock = tcp_socket(@host, @port)
22662272
begin
@@ -2632,6 +2638,7 @@ def start_tls_session(params = {})
26322638
ssl_socket_connect(@sock, @open_timeout)
26332639
if context.verify_mode != VERIFY_NONE
26342640
@sock.post_connection_check(@host)
2641+
@tls_verified = true
26352642
end
26362643
end
26372644

test/net/imap/test_imap.rb

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,41 @@ def test_imaps_unknown_ca
4141
end
4242

4343
def test_imaps_with_ca_file
44+
# Assert verified *after* the imaps_test and assert_nothing_raised blocks.
45+
# Otherwise, failures can't logout and need to wait for the timeout.
46+
verified, imap = :unknown, nil
4447
assert_nothing_raised do
4548
imaps_test do |port|
46-
begin
47-
Net::IMAP.new("localhost",
48-
:port => port,
49-
:ssl => { :ca_file => CA_FILE })
50-
rescue SystemCallError
51-
skip $!
52-
end
49+
imap = Net::IMAP.new("localhost",
50+
port: port,
51+
ssl: { :ca_file => CA_FILE })
52+
verified = imap.tls_verified?
53+
imap
54+
rescue SystemCallError
55+
skip $!
5356
end
5457
end
58+
assert_equal true, verified
59+
assert_equal true, imap.tls_verified?
5560
end
5661

5762
def test_imaps_verify_none
63+
# Assert verified *after* the imaps_test and assert_nothing_raised blocks.
64+
# Otherwise, failures can't logout and need to wait for the timeout.
65+
verified, imap = :unknown, nil
5866
assert_nothing_raised do
5967
imaps_test do |port|
60-
Net::IMAP.new(server_addr,
61-
:port => port,
62-
:ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE })
68+
imap = Net::IMAP.new(
69+
server_addr,
70+
port: port,
71+
ssl: { :verify_mode => OpenSSL::SSL::VERIFY_NONE }
72+
)
73+
verified = imap.tls_verified?
74+
imap
6375
end
6476
end
77+
assert_equal false, verified
78+
assert_equal false, imap.tls_verified?
6579
end
6680

6781
def test_imaps_post_connection_check
@@ -79,12 +93,15 @@ def test_imaps_post_connection_check
7993

8094
if defined?(OpenSSL::SSL)
8195
def test_starttls
82-
imap = nil
96+
verified, imap = :unknown, nil
8397
starttls_test do |port|
8498
imap = Net::IMAP.new("localhost", :port => port)
8599
imap.starttls(:ca_file => CA_FILE)
100+
verified = imap.tls_verified?
86101
imap
87102
end
103+
assert_equal true, verified
104+
assert_equal true, imap.tls_verified?
88105
rescue SystemCallError
89106
skip $!
90107
ensure
@@ -94,13 +111,17 @@ def test_starttls
94111
end
95112

96113
def test_starttls_stripping
114+
verified, imap = :unknown, nil
97115
starttls_stripping_test do |port|
98116
imap = Net::IMAP.new("localhost", :port => port)
99117
assert_raise(Net::IMAP::UnknownResponseError) do
100118
imap.starttls(:ca_file => CA_FILE)
101119
end
120+
verified = imap.tls_verified?
102121
imap
103122
end
123+
assert_equal false, verified
124+
assert_equal false, imap.tls_verified?
104125
end
105126
end
106127

@@ -1068,6 +1089,7 @@ def imaps_test(timeout: 10)
10681089
begin
10691090
imap = yield(port)
10701091
imap.logout
1092+
imap
10711093
ensure
10721094
imap.disconnect if imap
10731095
end

0 commit comments

Comments
 (0)