Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions lib/net/imap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,7 @@ def starttls(**options)
# completes. If the TaggedResponse to #authenticate includes updated
# capabilities, they will be cached.
def authenticate(*args, sasl_ir: config.sasl_ir, **props, &callback)
sasl_ir = may_depend_on_capabilities_cached?(sasl_ir)
sasl_adapter.authenticate(*args, sasl_ir: sasl_ir, **props, &callback)
.tap do state_authenticated! _1 end
end
Expand Down Expand Up @@ -3578,11 +3579,11 @@ def put_string(str)
end

def enforce_logindisabled?
if config.enforce_logindisabled == :when_capabilities_cached
capabilities_cached?
else
config.enforce_logindisabled
end
may_depend_on_capabilities_cached?(config.enforce_logindisabled)
end

def may_depend_on_capabilities_cached?(value)
value == :when_capabilities_cached ? capabilities_cached? : value
end

def expunge_internal(...)
Expand Down
15 changes: 14 additions & 1 deletion lib/net/imap/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,26 @@ def self.[](config)
# Do not use +SASL-IR+, even when it is supported by the server and the
# mechanism.
#
# [+:when_capabilities_cached+]
# Use +SASL-IR+ when Net::IMAP#capabilities_cached? is +true+ and it is
# supported by the server and the mechanism, but do not send a
# +CAPABILITY+ command to discover the server capabilities.
#
# <em>(+:when_capabilities_cached+ option was added by +v0.6.0+)</em>
#
# [+true+ <em>(default since +v0.4+)</em>]
# Use +SASL-IR+ when it is supported by the server and the mechanism.
attr_accessor :sasl_ir, type: :boolean, defaults: {
attr_accessor :sasl_ir, type: Enum[
false, :when_capabilities_cached, true
], defaults: {
0.0r => false,
0.4r => true,
}

# :stopdoc:
alias sasl_ir? sasl_ir
# :startdoc:

# Controls the behavior of Net::IMAP#login when the +LOGINDISABLED+
# capability is present. When enforced, Net::IMAP will raise a
# LoginDisabledError when that capability is present.
Expand Down
52 changes: 52 additions & 0 deletions test/net/imap/test_imap_authenticate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,58 @@ class IMAPAuthenticateTest < Net::IMAP::TestCase
end
end

test("#authenticate without cached capabilities never sends initial response " \
"when config.sasl_ir: :when_capabilities_cached") do
[true, false].each do |server_support|
with_fake_server(
preauth: false, cleartext_auth: true, sasl_ir: server_support,
greeting_capabilities: false,
) do |server, imap|
imap.config.sasl_ir = :when_capabilities_cached
imap.authenticate("PLAIN", "test_user", "test-password")
cmd, cont = 2.times.map { server.commands.pop }
assert_equal %w[AUTHENTICATE PLAIN], [cmd.name, *cmd.args]
assert_equal(["\x00test_user\x00test-password"].pack("m0"),
cont[:continuation].strip)
assert_empty server.commands
end
end
end

test("#authenticate with cached capabilities sends an initial response " \
"when config.sasl_ir: :when_capabilities_cached " \
"and supported by both the mechanism and the server") do
with_fake_server(
preauth: false, cleartext_auth: true, sasl_ir: true,
greeting_capabilities: true,
) do |server, imap|
imap.config.sasl_ir = :when_capabilities_cached
imap.authenticate("PLAIN", "test_user", "test-password")
cmd = server.commands.pop
assert_equal "AUTHENTICATE", cmd.name
assert_equal(["PLAIN", ["\x00test_user\x00test-password"].pack("m0")],
cmd.args)
assert_empty server.commands
end
end

test("#authenticate with cached capabilities doesn't send initial response " \
"when config.sasl_ir: :when_capabilities_cached " \
"and not supported by the server") do
with_fake_server(
preauth: false, cleartext_auth: true, sasl_ir: false,
greeting_capabilities: true,
) do |server, imap|
imap.config.sasl_ir = :when_capabilities_cached
imap.authenticate("PLAIN", "test_user", "test-password")
cmd, cont = 2.times.map { server.commands.pop }
assert_equal %w[AUTHENTICATE PLAIN], [cmd.name, *cmd.args]
assert_equal(["\x00test_user\x00test-password"].pack("m0"),
cont[:continuation].strip)
assert_empty server.commands
end
end

test("#authenticate never sends an initial response " \
"when config.sasl_ir: false") do
[true, false].each do |server_support|
Expand Down