This is an automated email from the ASF dual-hosted git repository. rnewson pushed a commit to branch decouple_offline_hash_strength_from_online in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 1f33d6a0bd849d6e0cbfd3955426bcc2bfe8bc37 Author: Robert Newson <[email protected]> AuthorDate: Mon Oct 23 18:32:22 2023 +0100 remove all password derivation fields before adding back the new ones --- src/couch/src/couch_users_db.erl | 48 +++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/couch/src/couch_users_db.erl b/src/couch/src/couch_users_db.erl index a32591d99..e3b914969 100644 --- a/src/couch/src/couch_users_db.erl +++ b/src/couch/src/couch_users_db.erl @@ -27,7 +27,6 @@ -define(PRESERVE_SALT, <<"preserve_salt">>). -define(ITERATIONS, <<"iterations">>). -define(SALT, <<"salt">>). --define(replace(L, K, V), lists:keystore(K, 1, L, {K, V})). -define(REQUIREMENT_ERROR, "Password does not conform to requirements."). -define(PASSWORD_SERVER_ERROR, "Server cannot hash passwords at this time."). @@ -90,12 +89,14 @@ save_doc(#doc{body = {Body}} = Doc) -> {ClearPassword, "simple"} -> ok = validate_password(ClearPassword), PasswordSha = couch_passwords:simple(ClearPassword, Salt), - Body0 = ?replace(Body, ?PASSWORD_SCHEME, ?SIMPLE), - Body1 = ?replace(Body0, ?SALT, Salt), - Body2 = ?replace(Body1, ?PASSWORD_SHA, PasswordSha), - Body3 = proplists:delete(?PRESERVE_SALT, Body2), - Body4 = proplists:delete(?PASSWORD, Body3), - Doc#doc{body = {Body4}}; + Body0 = remove_password_fields(Body), + Body1 = [ + {?PASSWORD_SCHEME, ?SIMPLE}, + {?SALT, Salt}, + {?PASSWORD_SHA, PasswordSha} + | Body0 + ], + Doc#doc{body = {Body1}}; {ClearPassword, "pbkdf2"} -> ok = validate_password(ClearPassword), PRF = chttpd_util:get_chttpd_auth_config("pbkdf2_prf", "sha256"), @@ -105,19 +106,36 @@ save_doc(#doc{body = {Body}} = Doc) -> DerivedKey = couch_passwords:pbkdf2( list_to_existing_atom(PRF), ClearPassword, Salt, Iterations ), - Body0 = ?replace(Body, ?PASSWORD_SCHEME, ?PBKDF2), - Body1 = ?replace(Body0, ?PBKDF2_PRF, ?l2b(PRF)), - Body2 = ?replace(Body1, ?ITERATIONS, Iterations), - Body3 = ?replace(Body2, ?DERIVED_KEY, DerivedKey), - Body4 = ?replace(Body3, ?SALT, Salt), - Body5 = proplists:delete(?PRESERVE_SALT, Body4), - Body6 = proplists:delete(?PASSWORD, Body5), - Doc#doc{body = {Body6}}; + Body0 = remove_password_fields(Body), + Body1 = [ + {?PASSWORD_SCHEME, ?PBKDF2}, + {?PBKDF2_PRF, ?l2b(PRF)}, + {?SALT, Salt}, + {?ITERATIONS, Iterations}, + {?DERIVED_KEY, DerivedKey} + | Body0 + ], + Doc#doc{body = {Body1}}; {_ClearPassword, Scheme} -> couch_log:error("[couch_httpd_auth] password_scheme value of '~p' is invalid.", [Scheme]), throw({forbidden, ?PASSWORD_SERVER_ERROR}) end. +remove_password_fields(Props) -> + lists:filter(fun not_password_field/1, Props). + +not_password_field({Key, _Value}) -> + not lists:member(Key, [ + ?DERIVED_KEY, + ?ITERATIONS, + ?PASSWORD, + ?PASSWORD_SCHEME, + ?PASSWORD_SHA, + ?PRESERVE_SALT, + ?PBKDF2_PRF, + ?SALT + ]). + % Validate if a new password matches all RegExp in the password_regexp setting. % Throws if not. % In this function the [couch_httpd_auth] password_regexp config is parsed.
