diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl index b669c2610f..d013625da1 100644 --- a/src/couch/src/couch_httpd_auth.erl +++ b/src/couch/src/couch_httpd_auth.erl @@ -109,14 +109,19 @@ default_authentication_handler(Req, AuthModule) -> case AuthModule:get_user_creds(Req, User) of nil -> throw({unauthorized, <<"Name or password is incorrect.">>}); - {ok, UserProps, _AuthCtx} -> + {ok, UserProps, AuthCtx} -> reject_if_totp(UserProps), UserName = ?l2b(User), Password = ?l2b(Pass), case authenticate(Req, AuthModule, UserName, Password, UserProps) of true -> couch_password_hasher:maybe_upgrade_password_hash( - AuthModule, UserName, Password, UserProps + Req, + UserName, + Password, + UserProps, + AuthModule, + AuthCtx ), Req#httpd{ user_ctx = #user_ctx{ @@ -497,7 +502,7 @@ handle_session_req(#httpd{method = 'POST', mochi_req = MochiReq} = Req, AuthModu UserName = ?l2b(extract_username(Form)), Password = ?l2b(couch_util:get_value("password", Form, "")), couch_log:debug("Attempt Login: ~s", [UserName]), - {ok, UserProps, _AuthCtx} = + {ok, UserProps, AuthCtx} = case AuthModule:get_user_creds(Req, UserName) of nil -> {ok, [], nil}; Result -> Result @@ -506,7 +511,7 @@ handle_session_req(#httpd{method = 'POST', mochi_req = MochiReq} = Req, AuthModu true -> verify_totp(UserProps, Form), couch_password_hasher:maybe_upgrade_password_hash( - AuthModule, UserName, Password, UserProps + Req, UserName, Password, UserProps, AuthModule, AuthCtx ), % setup the session cookie Secret = ?l2b(ensure_cookie_auth_secret()), diff --git a/src/couch/src/couch_password_hasher.erl b/src/couch/src/couch_password_hasher.erl index e240852245..75cf404325 100644 --- a/src/couch/src/couch_password_hasher.erl +++ b/src/couch/src/couch_password_hasher.erl @@ -24,7 +24,7 @@ handle_info/2 ]). --export([maybe_upgrade_password_hash/4, hash_admin_passwords/1]). +-export([maybe_upgrade_password_hash/6, hash_admin_passwords/1]). -export([worker_loop/1]). @@ -38,7 +38,7 @@ %%% Public functions %%%=================================================================== -maybe_upgrade_password_hash(AuthModule, UserName, Password, UserProps) -> +maybe_upgrade_password_hash(Req, UserName, Password, UserProps, AuthModule, AuthCtx) -> UpgradeEnabled = config:get_boolean("chttpd_auth", "upgrade_hash_on_auth", false), IsDoc = is_doc(UserProps), NeedsUpgrade = needs_upgrade(UserProps), @@ -46,7 +46,8 @@ maybe_upgrade_password_hash(AuthModule, UserName, Password, UserProps) -> if UpgradeEnabled andalso IsDoc andalso NeedsUpgrade andalso not InProgress -> gen_server:cast( - ?MODULE, {upgrade_password_hash, AuthModule, UserName, Password, UserProps} + ?MODULE, + {upgrade_password_hash, Req, UserName, Password, UserProps, AuthModule, AuthCtx} ); true -> ok @@ -72,11 +73,13 @@ init(_Args) -> handle_call(Msg, _From, #state{} = State) -> {stop, {invalid_call, Msg}, {invalid_call, Msg}, State}. -handle_cast({upgrade_password_hash, AuthModule, UserName, Password, UserProps}, State) -> +handle_cast( + {upgrade_password_hash, Req, UserName, Password, UserProps, AuthModule, AuthCtx}, State +) -> case ets:insert_new(?IN_PROGRESS_ETS, {{AuthModule, UserName}}) of true -> State#state.worker_pid ! - {upgrade_password_hash, AuthModule, UserName, Password, UserProps}; + {upgrade_password_hash, Req, UserName, Password, UserProps, AuthModule, AuthCtx}; false -> ok end, @@ -136,14 +139,16 @@ start_worker_loop(State) -> worker_loop(Parent) -> receive - {upgrade_password_hash, AuthModule, UserName, Password, UserProps} -> - couch_log:notice("upgrading stored password hash for '~s'", [UserName]), - upgrade_password_hash(AuthModule, Password, UserProps), - erlang:send_after(5000, Parent, {done, AuthModule, UserName}) + {upgrade_password_hash, Req, UserName, Password, UserProps, AuthModule, AuthCtx} -> + couch_log:notice("upgrading stored password hash for '~s' (~p)", [UserName, AuthCtx]), + upgrade_password_hash(Req, UserName, Password, UserProps, AuthModule, AuthCtx), + erlang:send_after(5000, Parent, {done, AuthModule, UserName}); + _Msg -> + ignore end, worker_loop(Parent). -upgrade_password_hash(AuthModule, Password, UserProps0) -> +upgrade_password_hash(Req, _UserName, Password, UserProps0, AuthModule, AuthCtx) -> UserProps1 = [{<<"password">>, Password}, {<<"preserve_salt">>, true} | UserProps0], NewUserDoc = couch_doc:from_json_obj({UserProps1}), - catch AuthModule:update_user_creds(nil, NewUserDoc, ?ADMIN_CTX). + catch AuthModule:update_user_creds(Req, NewUserDoc, AuthCtx).