diff --git a/lib/net/imap/authenticators/login.rb b/lib/net/imap/authenticators/login.rb deleted file mode 100644 index 6d3ed833..00000000 --- a/lib/net/imap/authenticators/login.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -# Authenticator for the "+LOGIN+" SASL mechanism. See Net::IMAP#authenticate. -# -# +LOGIN+ authentication sends the password in cleartext. -# RFC3501[https://tools.ietf.org/html/rfc3501] encourages servers to disable -# cleartext authentication until after TLS has been negotiated. -# RFC8314[https://tools.ietf.org/html/rfc8314] recommends TLS version 1.2 or -# greater be used for all traffic, and deprecate cleartext access ASAP. +LOGIN+ -# can be secured by TLS encryption. -# -# == Deprecated -# -# The {SASL mechanisms -# registry}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml] -# marks "LOGIN" as obsoleted in favor of "PLAIN". It is included here for -# compatibility with existing servers. See -# {draft-murchison-sasl-login}[https://www.iana.org/go/draft-murchison-sasl-login] -# for both specification and deprecation. -class Net::IMAP::LoginAuthenticator - def process(data) - case @state - when STATE_USER - @state = STATE_PASSWORD - return @user - when STATE_PASSWORD - return @password - end - end - - private - - STATE_USER = :USER - STATE_PASSWORD = :PASSWORD - - def initialize(user, password, warn_deprecation: true, **_ignored) - if warn_deprecation - warn "WARNING: LOGIN SASL mechanism is deprecated. Use PLAIN instead." - end - @user = user - @password = password - @state = STATE_USER - end - -end diff --git a/lib/net/imap/sasl.rb b/lib/net/imap/sasl.rb index 56d6afbd..3e09b7f9 100644 --- a/lib/net/imap/sasl.rb +++ b/lib/net/imap/sasl.rb @@ -67,13 +67,14 @@ module SASL autoload :CramMD5Authenticator, "#{sasl_dir}/cram_md5_authenticator" autoload :DigestMD5Authenticator, "#{sasl_dir}/digest_md5_authenticator" + autoload :LoginAuthenticator, "#{sasl_dir}/login_authenticator" # Authenticators are all lazy loaded def self.authenticators @authenticators ||= SASL::Authenticators.new.tap do |registry| registry.add_authenticator "Plain" registry.add_authenticator "XOAuth2" - registry.add_authenticator "Login", LoginAuthenticator # deprecated + registry.add_authenticator "Login" # deprecated registry.add_authenticator "Cram-MD5" # deprecated registry.add_authenticator "Digest-MD5" # deprecated end @@ -105,5 +106,3 @@ def saslprep(string, **opts) end end end - -require_relative "authenticators/login" diff --git a/lib/net/imap/sasl/login_authenticator.rb b/lib/net/imap/sasl/login_authenticator.rb new file mode 100644 index 00000000..3dd595ae --- /dev/null +++ b/lib/net/imap/sasl/login_authenticator.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Net + class IMAP < Protocol + module SASL + + # Authenticator for the "+LOGIN+" SASL mechanism. See Net::IMAP#authenticate. + # + # +LOGIN+ authentication sends the password in cleartext. + # RFC3501[https://tools.ietf.org/html/rfc3501] encourages servers to disable + # cleartext authentication until after TLS has been negotiated. + # RFC8314[https://tools.ietf.org/html/rfc8314] recommends TLS version 1.2 or + # greater be used for all traffic, and deprecate cleartext access ASAP. +LOGIN+ + # can be secured by TLS encryption. + # + # == Deprecated + # + # The {SASL mechanisms + # registry}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml] + # marks "LOGIN" as obsoleted in favor of "PLAIN". It is included here for + # compatibility with existing servers. See + # {draft-murchison-sasl-login}[https://www.iana.org/go/draft-murchison-sasl-login] + # for both specification and deprecation. + class LoginAuthenticator + + STATE_USER = :USER + STATE_PASSWORD = :PASSWORD + STATE_DONE = :DONE + private_constant :STATE_USER, :STATE_PASSWORD, :STATE_DONE + + def initialize(user, password, warn_deprecation: true, **_ignored) + if warn_deprecation + warn "WARNING: LOGIN SASL mechanism is deprecated. Use PLAIN instead." + end + @user = user + @password = password + @state = STATE_USER + end + + def process(data) + case @state + when STATE_USER + @state = STATE_PASSWORD + @user + when STATE_PASSWORD + @state = STATE_DONE + @password + when STATE_DONE + raise ResponseParseError, data + end + end + + def done?; @state == STATE_DONE end + end + end + + LoginAuthenticator = SASL::LoginAuthenticator # :nodoc: + deprecate_constant :LoginAuthenticator + + end +end diff --git a/test/net/imap/test_imap_authenticators.rb b/test/net/imap/test_imap_authenticators.rb index 2c430b45..5e143706 100644 --- a/test/net/imap/test_imap_authenticators.rb +++ b/test/net/imap/test_imap_authenticators.rb @@ -97,7 +97,7 @@ def login(*args, warn_deprecation: false, **kwargs, &block) end def test_login_authenticator_matches_mechanism - assert_kind_of(Net::IMAP::LoginAuthenticator, login("n", "p")) + assert_kind_of(Net::IMAP::SASL::LoginAuthenticator, login("n", "p")) end def test_login_authenticator_deprecated