diff --git a/rebar.config b/rebar.config index 192c7b18c..16cde2cc4 100644 --- a/rebar.config +++ b/rebar.config @@ -77,7 +77,7 @@ {stringprep, "~> 1.0.31", {git, "https://github.com/processone/stringprep", {tag, "1.0.31"}}}, {if_var_true, stun, {stun, "~> 1.2.17", {git, "https://github.com/processone/stun", {tag, "1.2.17"}}}}, - {xmpp, "~> 1.10.0", {git, "https://github.com/processone/xmpp", "9b028c110083e4d979d88c286873d0abf08fa532"}}, + {xmpp, "~> 1.10.0", {git, "https://github.com/processone/xmpp", "b474d673938856a546265cd5db1139244bfb95f3"}}, {yconf, "~> 1.0.18", {git, "https://github.com/processone/yconf", {tag, "1.0.18"}}} ]}. diff --git a/rebar.lock b/rebar.lock index caac96087..c42e49c40 100644 --- a/rebar.lock +++ b/rebar.lock @@ -35,7 +35,7 @@ {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.1">>},1}, {<<"xmpp">>, {git,"https://github.com/processone/xmpp", - {ref,"9b028c110083e4d979d88c286873d0abf08fa532"}}, + {ref,"b474d673938856a546265cd5db1139244bfb95f3"}}, 0}, {<<"yconf">>,{pkg,<<"yconf">>,<<"1.0.18">>},0}]}. [ diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 1852dde32..1a03adc9f 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -440,21 +440,32 @@ sasl_mechanisms(Mechs, #{lserver := LServer, stream_encrypted := Encrypted} = St end, %% I re-created it from cyrsasl ets magic, but I think it's wrong %% TODO: need to check before 18.09 release - lists:filter( - fun(<<"ANONYMOUS">>) -> - ejabberd_auth_anonymous:is_sasl_anonymous_enabled(LServer); - (<<"DIGEST-MD5">>) -> Digest; - (<<"SCRAM-SHA-1">>) -> ShaAv; - (<<"SCRAM-SHA-1-PLUS">>) -> ShaAv andalso Encrypted; - (<<"SCRAM-SHA-256">>) -> Sha256Av; - (<<"SCRAM-SHA-256-PLUS">>) -> Sha256Av andalso Encrypted; - (<<"SCRAM-SHA-512">>) -> Sha512Av; - (<<"SCRAM-SHA-512-PLUS">>) -> Sha512Av andalso Encrypted; - (<<"PLAIN">>) -> true; - (<<"X-OAUTH2">>) -> [ejabberd_auth_anonymous] /= ejabberd_auth:auth_modules(LServer); - (<<"EXTERNAL">>) -> maps:get(tls_verify, State, false); - (_) -> false - end, Mechs -- Mechs1). + Mechs2 = lists:filter( + fun(<<"ANONYMOUS">>) -> + ejabberd_auth_anonymous:is_sasl_anonymous_enabled(LServer); + (<<"DIGEST-MD5">>) -> Digest; + (<<"SCRAM-SHA-1">>) -> ShaAv; + (<<"SCRAM-SHA-1-PLUS">>) -> ShaAv andalso Encrypted; + (<<"SCRAM-SHA-256">>) -> Sha256Av; + (<<"SCRAM-SHA-256-PLUS">>) -> Sha256Av andalso Encrypted; + (<<"SCRAM-SHA-512">>) -> Sha512Av; + (<<"SCRAM-SHA-512-PLUS">>) -> Sha512Av andalso Encrypted; + (<<"PLAIN">>) -> true; + (<<"X-OAUTH2">>) -> [ejabberd_auth_anonymous] /= ejabberd_auth:auth_modules(LServer); + (<<"EXTERNAL">>) -> maps:get(tls_verify, State, false); + (_) -> false + end, Mechs -- Mechs1), + case ejabberd_option:auth_password_types_hidden_in_scram1() of + [] -> Mechs2; + List -> + Mechs3 = lists:foldl( + fun(plain, Acc) -> Acc -- [<<"PLAIN">>]; + (scram_sha1, Acc) -> Acc -- [<<"SCRAM-SHA-1">>, <<"SCRAM-SHA-1-PLUS">>]; + (scram_sha256, Acc) -> Acc -- [<<"SCRAM-SHA-256">>, <<"SCRAM-SHA-256-PLUS">>]; + (scram_sha512, Acc) -> Acc -- [<<"SCRAM-SHA-512">>, <<"SCRAM-SHA-512-PLUS">>] + end, Mechs2, List), + {Mechs3, Mechs2} + end. sasl_options(#{lserver := LServer}) -> case ejabberd_option:disable_sasl_scram_downgrade_protection(LServer) of diff --git a/src/ejabberd_option.erl b/src/ejabberd_option.erl index 3a69da867..4361571f8 100644 --- a/src/ejabberd_option.erl +++ b/src/ejabberd_option.erl @@ -18,6 +18,7 @@ -export([auth_method/0, auth_method/1]). -export([auth_opts/0, auth_opts/1]). -export([auth_password_format/0, auth_password_format/1]). +-export([auth_password_types_hidden_in_scram1/0, auth_password_types_hidden_in_scram1/1]). -export([auth_scram_hash/0, auth_scram_hash/1]). -export([auth_stored_password_types/0, auth_stored_password_types/1]). -export([auth_use_cache/0, auth_use_cache/1]). @@ -263,6 +264,13 @@ auth_password_format() -> auth_password_format(Host) -> ejabberd_config:get_option({auth_password_format, Host}). +-spec auth_password_types_hidden_in_scram1() -> ['plain' | 'scram_sha1' | 'scram_sha256' | 'scram_sha512']. +auth_password_types_hidden_in_scram1() -> + auth_password_types_hidden_in_scram1(global). +-spec auth_password_types_hidden_in_scram1(global | binary()) -> ['plain' | 'scram_sha1' | 'scram_sha256' | 'scram_sha512']. +auth_password_types_hidden_in_scram1(Host) -> + ejabberd_config:get_option({auth_password_types_hidden_in_scram1, Host}). + -spec auth_scram_hash() -> 'sha' | 'sha256' | 'sha512'. auth_scram_hash() -> auth_scram_hash(global). diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl index 521687aa2..ee3acfc58 100644 --- a/src/ejabberd_options.erl +++ b/src/ejabberd_options.erl @@ -79,6 +79,8 @@ opt_type(auth_opts) -> end; opt_type(auth_stored_password_types) -> econf:list(econf:enum([plain, scram_sha1, scram_sha256, scram_sha512])); +opt_type(auth_password_types_hidden_in_scram1) -> + econf:list(econf:enum([plain, scram_sha1, scram_sha256, scram_sha512])); opt_type(auth_password_format) -> econf:enum([plain, scram]); opt_type(auth_scram_hash) -> @@ -564,6 +566,7 @@ options() -> {auth_password_format, plain}, {auth_scram_hash, sha}, {auth_stored_password_types, []}, + {auth_password_types_hidden_in_scram1, []}, {auth_external_user_exists_check, true}, {auth_use_cache, fun(Host) -> ejabberd_config:get_option({use_cache, Host}) end}, diff --git a/src/ejabberd_options_doc.erl b/src/ejabberd_options_doc.erl index dabfae06d..98f170c96 100644 --- a/src/ejabberd_options_doc.erl +++ b/src/ejabberd_options_doc.erl @@ -392,6 +392,17 @@ doc() -> "SASL PLAIN and SASL SCRAM-SHA-1/256/512(-PLUS). The SCRAM variant " "depends on the _`auth_scram_hash`_ option."), "", ?T("The default value is 'plain'."), ""]}}, + + {auth_password_types_hidden_in_scram1, + #{value => "[plain | scram_sha1 | scram_sha256 | scram_sha512]", + note => "added in 25.07", + desc => + ?T("List of password types that should not be offered in SCRAM1 authenticatication. " + "Because SCRAM1, unlike SCRAM2, can't have list of available mechanisms tailored to " + "individual user, it's possible that offered mechanisms will not be compatible " + "with stored password, especially if new password type was added recently. " + "This option allows disabling offering some mechanisms in SASL1, to a time until new " + "password type will be available for all users.")}}, {auth_scram_hash, #{value => "sha | sha256 | sha512", desc =>