summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonny <ronny@apache.org>2022-07-18 19:01:30 +0200
committerGitHub <noreply@github.com>2022-07-18 19:01:30 +0200
commitdaff65d8c8772c637eb60365d6e672543163a740 (patch)
tree3d3cbdefc48f985d25228a0a7f39ca48de4a6b7d
parent7fb96d2652ebccad8479d9d29a02ce76cd6e853b (diff)
downloadcouchdb-daff65d8c8772c637eb60365d6e672543163a740.tar.gz
Replace SHA-1 with SHA-256 for cookie authentication (#4094)
* Replace Sha-1 with Sha-256 for cookie authentication * Fix proxyauth_test and remove it from skipping tests
-rw-r--r--src/couch/src/couch_httpd_auth.erl18
-rw-r--r--test/elixir/test/config/skip.elixir4
-rw-r--r--test/elixir/test/proxyauth_test.exs99
3 files changed, 43 insertions, 78 deletions
diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl
index 47096e120..4fa5d04df 100644
--- a/src/couch/src/couch_httpd_auth.erl
+++ b/src/couch/src/couch_httpd_auth.erl
@@ -153,14 +153,14 @@ null_authentication_handler(Req) ->
% Headers name can be defined in local.ini. By default they are :
%
% * X-Auth-CouchDB-UserName : contain the username, (x_auth_username in
-% couch_httpd_auth section)
+% cttpd_auth section)
% * X-Auth-CouchDB-Roles : contain the user roles, list of roles separated by a
-% comma (x_auth_roles in couch_httpd_auth section)
+% comma (x_auth_roles in chttpd_auth section)
% * X-Auth-CouchDB-Token : token to authenticate the authorization (x_auth_token
-% in couch_httpd_auth section). This token is an hmac-sha1 created from secret key
+% in chttpd_auth section). This token is an hmac-sha256 created from secret key
% and username. The secret key should be the same in the client and couchdb node.
-% Secret key is the secret key in couch_httpd_auth section of ini. This token is optional
-% if value of proxy_use_secret key in couch_httpd_auth section of ini isn't true.
+% Secret key is the secret key in chttpd_auth section of ini. This token is optional
+% if value of proxy_use_secret key in chttpd_auth section of ini isn't true.
%
proxy_authentication_handler(Req) ->
case proxy_auth_user(Req) of
@@ -202,7 +202,7 @@ proxy_auth_user(Req) ->
Req#httpd{user_ctx = #user_ctx{name = ?l2b(UserName), roles = Roles}};
Secret ->
ExpectedToken = couch_util:to_hex(
- couch_util:hmac(sha, Secret, UserName)
+ couch_util:hmac(sha256, Secret, UserName)
),
case header_value(Req, XHeaderToken) of
Token when Token == ExpectedToken ->
@@ -308,7 +308,9 @@ cookie_authentication_handler(#httpd{mochi_req = MochiReq} = Req, AuthModule) ->
{ok, UserProps, _AuthCtx} ->
UserSalt = couch_util:get_value(<<"salt">>, UserProps, <<"">>),
FullSecret = <<Secret/binary, UserSalt/binary>>,
- ExpectedHash = couch_util:hmac(sha, FullSecret, User ++ ":" ++ TimeStr),
+ ExpectedHash = couch_util:hmac(
+ sha256, FullSecret, User ++ ":" ++ TimeStr
+ ),
Hash = ?l2b(HashStr),
Timeout = chttpd_util:get_chttpd_auth_config_integer(
"timeout", 600
@@ -367,7 +369,7 @@ cookie_auth_header(_Req, _Headers) ->
cookie_auth_cookie(Req, User, Secret, TimeStamp) ->
SessionData = User ++ ":" ++ erlang:integer_to_list(TimeStamp, 16),
- Hash = couch_util:hmac(sha, Secret, SessionData),
+ Hash = couch_util:hmac(sha256, Secret, SessionData),
mochiweb_cookies:cookie(
"AuthSession",
couch_util:encodeBase64Url(SessionData ++ ":" ++ ?b2l(Hash)),
diff --git a/test/elixir/test/config/skip.elixir b/test/elixir/test/config/skip.elixir
index bb27f13cd..7fbcacef7 100644
--- a/test/elixir/test/config/skip.elixir
+++ b/test/elixir/test/config/skip.elixir
@@ -2,10 +2,6 @@
"CookieAuthTest": [
"cookie auth"
],
- "ProxyAuthTest": [
- "proxy auth with secret",
- "proxy auth without secret"
- ],
"ReaderACLTest": [
"unrestricted db can be read"
],
diff --git a/test/elixir/test/proxyauth_test.exs b/test/elixir/test/proxyauth_test.exs
index 6bf21920b..6a4b58561 100644
--- a/test/elixir/test/proxyauth_test.exs
+++ b/test/elixir/test/proxyauth_test.exs
@@ -4,27 +4,7 @@ defmodule ProxyAuthTest do
@moduletag :authentication
@tag :with_db
- test "proxy auth with secret", context do
- db_name = context[:db_name]
-
- design_doc = %{
- _id: "_design/test",
- language: "javascript",
- shows: %{
- welcome: """
- function(doc,req) {
- return "Welcome " + req.userCtx["name"];
- }
- """,
- role: """
- function(doc, req) {
- return req.userCtx['roles'][0];
- }
- """
- }
- }
-
- {:ok, _} = create_doc(db_name, design_doc)
+ test "proxy auth with secret" do
users_db_name = random_db_name()
create_db(users_db_name)
@@ -38,19 +18,19 @@ defmodule ProxyAuthTest do
:value => users_db_name
},
%{
- :section => "couch_httpd_auth",
+ :section => "chttpd_auth",
:key => "proxy_use_secret",
:value => "true"
},
%{
- :section => "couch_httpd_auth",
+ :section => "chttpd_auth",
:key => "secret",
:value => secret
}
]
run_on_modified_server(server_config, fn ->
- test_fun(db_name, users_db_name, secret)
+ test_fun(users_db_name, secret)
end)
delete_db(users_db_name)
end
@@ -62,16 +42,12 @@ defmodule ProxyAuthTest do
|> Enum.join("")
end
- defp hex_hmac_sha1(secret, message) do
- signature = case :erlang.system_info(:otp_release) do
- '20' -> :crypto.hmac(:sha, secret, message)
- '21' -> :crypto.hmac(:sha, secret, message)
- _ -> :crypto.mac(:hmac, :sha, secret, message)
- end
+ defp hex_hmac_sha256(secret, message) do
+ signature = :crypto.mac(:hmac, :sha256, secret, message)
Base.encode16(signature, case: :lower)
end
- def test_fun(db_name, users_db_name, secret) do
+ def test_fun(users_db_name, secret) do
user = prepare_user_doc(name: "couch@apache.org", password: "test")
create_doc(users_db_name, user)
@@ -85,38 +61,24 @@ defmodule ProxyAuthTest do
headers = [
"X-Auth-CouchDB-UserName": "couch@apache.org",
- "X-Auth-CouchDB-Roles": "test",
- "X-Auth-CouchDB-Token": hex_hmac_sha1(secret, "couch@apache.org")
+ "X-Auth-CouchDB-Roles": "test_role",
+ "X-Auth-CouchDB-Token": hex_hmac_sha256(secret, "couch@apache.org")
]
- resp = Couch.get("/#{db_name}/_design/test/_show/welcome", headers: headers)
- assert resp.body == "Welcome couch@apache.org"
- resp = Couch.get("/#{db_name}/_design/test/_show/role", headers: headers)
- assert resp.body == "test"
+ resp2 =
+ Couch.get("/_session",
+ headers: headers
+ )
+
+ assert resp2.body["userCtx"]["name"] == "couch@apache.org"
+ assert resp2.body["userCtx"]["roles"] == ["test_role"]
+ assert resp2.body["info"]["authenticated"] == "proxy"
+ assert resp2.body["ok"] == true
+
end
@tag :with_db
- test "proxy auth without secret", context do
- db_name = context[:db_name]
-
- design_doc = %{
- _id: "_design/test",
- language: "javascript",
- shows: %{
- welcome: """
- function(doc,req) {
- return "Welcome " + req.userCtx["name"];
- }
- """,
- role: """
- function(doc, req) {
- return req.userCtx['roles'][0];
- }
- """
- }
- }
-
- {:ok, _} = create_doc(db_name, design_doc)
+ test "proxy auth without secret" do
users_db_name = random_db_name()
create_db(users_db_name)
@@ -128,20 +90,20 @@ defmodule ProxyAuthTest do
:value => users_db_name
},
%{
- :section => "couch_httpd_auth",
+ :section => "chttpd_auth",
:key => "proxy_use_secret",
:value => "false"
}
]
run_on_modified_server(server_config, fn ->
- test_fun_no_secret(db_name, users_db_name)
+ test_fun_no_secret(users_db_name)
end)
delete_db(users_db_name)
end
- def test_fun_no_secret(db_name, users_db_name) do
+ def test_fun_no_secret(users_db_name) do
user = prepare_user_doc(name: "couch@apache.org", password: "test")
create_doc(users_db_name, user)
@@ -155,13 +117,18 @@ defmodule ProxyAuthTest do
headers = [
"X-Auth-CouchDB-UserName": "couch@apache.org",
- "X-Auth-CouchDB-Roles": "test"
+ "X-Auth-CouchDB-Roles": "test_role_1,test_role_2"
]
- resp = Couch.get("/#{db_name}/_design/test/_show/welcome", headers: headers)
- assert resp.body == "Welcome couch@apache.org"
+ resp2 =
+ Couch.get("/_session",
+ headers: headers
+ )
+
+ assert resp2.body["userCtx"]["name"] == "couch@apache.org"
+ assert resp2.body["userCtx"]["roles"] == ["test_role_1", "test_role_2"]
+ assert resp2.body["info"]["authenticated"] == "proxy"
+ assert resp2.body["ok"] == true
- resp = Couch.get("/#{db_name}/_design/test/_show/role", headers: headers)
- assert resp.body == "test"
end
end