You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2015/06/23 17:56:08 UTC
couch commit: updated refs/heads/master to 2c19dcd
Repository: couchdb-couch
Updated Branches:
refs/heads/master 04312dc9a -> 2c19dcd0c
Configurable password scheme
This gives the administrator control over which algorithm is used to
hash passwords and a separate control over whether this happens on
successful authentication or only at password change time.
closes COUCHDB-2725
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/2c19dcd0
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/2c19dcd0
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/2c19dcd0
Branch: refs/heads/master
Commit: 2c19dcd0c528b8dccafe92803edc4dff88e40909
Parents: 04312dc
Author: Robert Newson <rn...@apache.org>
Authored: Tue Jun 16 17:17:44 2015 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Tue Jun 23 14:08:22 2015 +0100
----------------------------------------------------------------------
src/couch_httpd_auth.erl | 6 ++++--
src/couch_passwords.erl | 9 +++++++++
src/couch_users_db.erl | 25 ++++++++++++++++++++-----
3 files changed, 33 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/2c19dcd0/src/couch_httpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_auth.erl b/src/couch_httpd_auth.erl
index 01453d8..0e78946 100644
--- a/src/couch_httpd_auth.erl
+++ b/src/couch_httpd_auth.erl
@@ -372,9 +372,11 @@ maybe_value(Key, Else, Fun) ->
maybe_upgrade_password_hash(Req, UserName, Password, UserProps,
AuthModule, AuthCtx) ->
+ Upgrade = config:get_boolean("couch_httpd_auth", "upgrade_password_on_auth", true),
IsAdmin = lists:member(<<"_admin">>, couch_util:get_value(<<"roles">>, UserProps, [])),
- case {IsAdmin, couch_util:get_value(<<"password_scheme">>, UserProps, <<"simple">>)} of
- {false, <<"simple">>} ->
+ case {IsAdmin, Upgrade,
+ couch_util:get_value(<<"password_scheme">>, UserProps, <<"simple">>)} of
+ {false, true, <<"simple">>} ->
UserProps2 = proplists:delete(<<"password_sha">>, UserProps),
UserProps3 = [{<<"password">>, Password} | UserProps2],
NewUserDoc = couch_doc:from_json_obj({UserProps3}),
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/2c19dcd0/src/couch_passwords.erl
----------------------------------------------------------------------
diff --git a/src/couch_passwords.erl b/src/couch_passwords.erl
index 2ab7cc3..b06a584 100644
--- a/src/couch_passwords.erl
+++ b/src/couch_passwords.erl
@@ -30,6 +30,15 @@ simple(Password, Salt) when is_binary(Password), is_binary(Salt) ->
hash_admin_password(ClearPassword) when is_list(ClearPassword) ->
hash_admin_password(?l2b(ClearPassword));
hash_admin_password(ClearPassword) when is_binary(ClearPassword) ->
+ %% Support both schemes to smooth migration from legacy scheme
+ Scheme = config:get("couch_httpd_auth", "password_scheme", "pbkdf2"),
+ hash_admin_password(Scheme, ClearPassword).
+
+hash_admin_password("simple", ClearPassword) -> % deprecated
+ Salt = couch_uuids:random(),
+ Hash = crypto:sha(<<ClearPassword/binary, Salt/binary>>),
+ ?l2b("-hashed-" ++ couch_util:to_hex(Hash) ++ "," ++ ?b2l(Salt));
+hash_admin_password("pbkdf2", ClearPassword) ->
Iterations = config:get("couch_httpd_auth", "iterations", "10000"),
Salt = couch_uuids:random(),
DerivedKey = couch_passwords:pbkdf2(couch_util:to_binary(ClearPassword),
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/2c19dcd0/src/couch_users_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_users_db.erl b/src/couch_users_db.erl
index ade1955..6f7b9af 100644
--- a/src/couch_users_db.erl
+++ b/src/couch_users_db.erl
@@ -20,6 +20,8 @@
-define(PASSWORD, <<"password">>).
-define(DERIVED_KEY, <<"derived_key">>).
-define(PASSWORD_SCHEME, <<"password_scheme">>).
+-define(SIMPLE, <<"simple">>).
+-define(PASSWORD_SHA, <<"password_sha">>).
-define(PBKDF2, <<"pbkdf2">>).
-define(ITERATIONS, <<"iterations">>).
-define(SALT, <<"salt">>).
@@ -57,12 +59,22 @@ before_doc_update(Doc, #db{user_ctx = UserCtx} = Db) ->
% newDoc.salt = salt
% newDoc.password = null
save_doc(#doc{body={Body}} = Doc) ->
- case couch_util:get_value(?PASSWORD, Body) of
- null -> % server admins don't have a user-db password entry
+ %% Support both schemes to smooth migration from legacy scheme
+ Scheme = config:get("couch_httpd_auth", "password_scheme", "pbkdf2"),
+ case {couch_util:get_value(?PASSWORD, Body), Scheme} of
+ {null, _} -> % server admins don't have a user-db password entry
Doc;
- undefined ->
+ {undefined, _} ->
Doc;
- ClearPassword ->
+ {ClearPassword, "simple"} -> % deprecated
+ Salt = couch_uuids:random(),
+ 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(?PASSWORD, Body2),
+ Doc#doc{body={Body3}};
+ {ClearPassword, "pbkdf2"} ->
Iterations = list_to_integer(config:get("couch_httpd_auth", "iterations", "1000")),
Salt = couch_uuids:random(),
DerivedKey = couch_passwords:pbkdf2(ClearPassword, Salt, Iterations),
@@ -71,7 +83,10 @@ save_doc(#doc{body={Body}} = Doc) ->
Body2 = ?replace(Body1, ?DERIVED_KEY, DerivedKey),
Body3 = ?replace(Body2, ?SALT, Salt),
Body4 = proplists:delete(?PASSWORD, Body3),
- Doc#doc{body={Body4}}
+ Doc#doc{body={Body4}};
+ {_ClearPassword, Scheme} ->
+ couch_log:error("[couch_httpd_auth] password_scheme value of '~p' is invalid.", [Scheme]),
+ throw({forbidden, "Server cannot hash passwords at this time."})
end.
% If the doc is a design doc