diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a2b97476..c10631b1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -40,7 +40,7 @@ jobs: sudo apt-get install -y gcc g++ make autoconf automake libtool \ libfcgi-dev libxml2-dev libmemcached-dev \ libboost-program-options-dev libcrypto++-dev libyajl-dev \ - libpqxx-dev zlib1g-dev libargon2-dev libfmt-dev + libpqxx-dev zlib1g-dev libfmt-dev - name: Autobuild uses: github/codeql-action/autobuild@v3 diff --git a/CMakeLists.txt b/CMakeLists.txt index fad3353a..9fa609fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,6 @@ find_package(Threads REQUIRED) find_package(PQXX 6.0 REQUIRED) find_package(LibXml2 2.6.31 REQUIRED) find_package(Libmemcached REQUIRED) -find_package(Argon2 REQUIRED) find_package(Boost 1.43 REQUIRED COMPONENTS program_options) target_compile_definitions(cgimap_common_compiler_options INTERFACE diff --git a/cmake/FindArgon2.cmake b/cmake/FindArgon2.cmake deleted file mode 100644 index 6ec69219..00000000 --- a/cmake/FindArgon2.cmake +++ /dev/null @@ -1,47 +0,0 @@ -find_package(PkgConfig) -pkg_check_modules(PC_Argon2 QUIET libargon2) - -find_path(Argon2_INCLUDE_DIR - NAMES argon2.h - PATHS ${PC_Argon2_INCLUDE_DIRS} - PATH_SUFFIXES argon2 -) -find_library(Argon2_LIBRARY - NAMES argon2 - PATHS ${PC_Argon2_LIBRARY_DIRS} -) - -set(Argon2_VERSION ${PC_Argon2_VERSION}) -set(Argon2_VERSION_STRING ${Argon2_VERSION}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Argon2 - FOUND_VAR Argon2_FOUND - REQUIRED_VARS - Argon2_LIBRARY - Argon2_INCLUDE_DIR - VERSION_VAR Argon2_VERSION -) - -if(Argon2_FOUND) - set(Argon2_LIBRARIES ${Argon2_LIBRARY}) - set(Argon2_INCLUDE_DIRS ${Argon2_INCLUDE_DIR}) - set(Argon2_DEFINITIONS ${PC_Argon2_CFLAGS_OTHER}) -endif() - -if(Argon2_FOUND AND NOT TARGET Argon2::Argon2) - add_library(Argon2::Argon2 UNKNOWN IMPORTED) - set_target_properties(Argon2::Argon2 PROPERTIES - IMPORTED_LOCATION "${Argon2_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${Argon2_INCLUDE_DIR}" - INTERFACE_COMPILE_OPTIONS "${PC_Argon2_CFLAGS_OTHER}" - VERSION "${Argon2_VERSION}" - ) -endif() - -mark_as_advanced( - Argon2_INCLUDE_DIR - Argon2_LIBRARY - Argon2_VERSION - Argon2_VERSION_STRING -) diff --git a/docker/debian/Dockerfile_bookworm b/docker/debian/Dockerfile_bookworm index 6372488c..b91317d4 100644 --- a/docker/debian/Dockerfile_bookworm +++ b/docker/debian/Dockerfile_bookworm @@ -7,7 +7,7 @@ RUN apt-get update -qq && \ apt-get install -y gcc g++ make cmake \ libfcgi-dev libxml2-dev libmemcached-dev libbrotli-dev \ libboost-program-options-dev libcrypto++-dev libyajl-dev \ - libpqxx-dev zlib1g-dev libargon2-dev libfmt-dev \ + libpqxx-dev zlib1g-dev libfmt-dev \ postgresql-15 postgresql-server-dev-all \ --no-install-recommends && \ apt-get clean && \ @@ -31,7 +31,7 @@ FROM debian:bookworm-slim RUN apt-get update -qq && \ apt-get install -y \ libfcgi-bin libmemcached11 libboost-program-options1.74.0 \ - libxml2 libcrypto++8 libyajl2 libpqxx-6.4 zlib1g libargon2-1 argon2 libfmt9 \ + libxml2 libcrypto++8 libyajl2 libpqxx-6.4 zlib1g libfmt9 \ --no-install-recommends && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/debian/Dockerfile_trixie b/docker/debian/Dockerfile_trixie index 6e30f05e..4f689489 100644 --- a/docker/debian/Dockerfile_trixie +++ b/docker/debian/Dockerfile_trixie @@ -7,7 +7,7 @@ RUN apt-get update -qq && \ apt-get install -y gcc g++ make cmake \ libfcgi-dev libxml2-dev libmemcached-dev libbrotli-dev \ libboost-program-options-dev libcrypto++-dev libyajl-dev \ - libpqxx-dev zlib1g-dev libargon2-dev libfmt-dev \ + libpqxx-dev zlib1g-dev libfmt-dev \ postgresql-16 postgresql-server-dev-all \ --no-install-recommends && \ apt-get clean && \ @@ -31,7 +31,7 @@ FROM debian:trixie RUN apt-get update -qq && \ apt-get install -y \ libfcgi-bin libmemcached11 libboost-program-options1.74.0 \ - libxml2 libcrypto++8 libyajl2 libpqxx-7.8 zlib1g libargon2-1 argon2 libfmt9 \ + libxml2 libcrypto++8 libyajl2 libpqxx-7.8 zlib1g libfmt9 \ --no-install-recommends && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index eeec2fe0..df9ebd6b 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -8,7 +8,7 @@ RUN apt-get update -qq && \ libfcgi-dev libxml2-dev libmemcached-dev libbrotli-dev \ libboost-program-options-dev \ libcrypto++-dev libyajl-dev \ - libpqxx-dev zlib1g-dev libargon2-dev libfmt-dev \ + libpqxx-dev zlib1g-dev libfmt-dev \ postgresql-12 postgresql-server-dev-all \ --no-install-recommends && \ apt-get clean && \ @@ -33,7 +33,7 @@ FROM ubuntu:20.04 RUN apt-get update -qq && \ apt-get install -y \ libfcgi-bin libmemcached11 libboost-locale1.71.0 libboost-program-options1.71.0 \ - libxml2 libcrypto++6 libyajl2 libpqxx-6.4 zlib1g libargon2-1 \ + libxml2 libcrypto++6 libyajl2 libpqxx-6.4 zlib1g \ --no-install-recommends && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/ubuntu/Dockerfile2204 b/docker/ubuntu/Dockerfile2204 index 6dadf7e6..cbe9715b 100644 --- a/docker/ubuntu/Dockerfile2204 +++ b/docker/ubuntu/Dockerfile2204 @@ -7,7 +7,7 @@ RUN apt-get update -qq && \ apt-get install -y gcc g++ make cmake \ libfcgi-dev libxml2-dev libmemcached-dev libbrotli-dev \ libboost-program-options-dev libcrypto++-dev libyajl-dev \ - libpqxx-dev zlib1g-dev libargon2-dev libfmt-dev \ + libpqxx-dev zlib1g-dev libfmt-dev \ postgresql-14 postgresql-server-dev-all \ --no-install-recommends && \ apt-get clean && \ @@ -31,7 +31,7 @@ FROM ubuntu:22.04 RUN apt-get update -qq && \ apt-get install -y \ libfcgi-bin libmemcached11 libboost-program-options1.74.0 \ - libxml2 libcrypto++8 libyajl2 libpqxx-6.4 zlib1g libargon2-1 argon2 libfmt8 \ + libxml2 libcrypto++8 libyajl2 libpqxx-6.4 zlib1g libfmt8 \ --no-install-recommends && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/include/cgimap/backend/apidb/readonly_pgsql_selection.hpp b/include/cgimap/backend/apidb/readonly_pgsql_selection.hpp index 904bce91..01a84fb0 100644 --- a/include/cgimap/backend/apidb/readonly_pgsql_selection.hpp +++ b/include/cgimap/backend/apidb/readonly_pgsql_selection.hpp @@ -74,7 +74,6 @@ class readonly_pgsql_selection : public data_selection { bool supports_user_details() const override; bool is_user_blocked(const osm_user_id_t) override; - bool get_user_id_pass(const std::string&, osm_user_id_t &, std::string &, std::string &) override; std::set< osm_user_role_t > get_roles_for_user(osm_user_id_t id) override; std::optional< osm_user_id_t > get_user_id_for_oauth2_token( const std::string &token_id, bool &expired, bool &revoked, diff --git a/include/cgimap/basicauth.hpp b/include/cgimap/basicauth.hpp deleted file mode 100644 index 65bebb3a..00000000 --- a/include/cgimap/basicauth.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/** - * SPDX-License-Identifier: GPL-2.0-only - * - * This file is part of openstreetmap-cgimap (https://github.com/zerebubuth/openstreetmap-cgimap/). - * - * Copyright (C) 2009-2023 by the CGImap developer community. - * For a full list of authors see the git log. - */ - -#ifndef BASICAUTH_HPP -#define BASICAUTH_HPP - -#include -#include - -#include "cgimap/data_selection.hpp" -#include "cgimap/http.hpp" -#include "cgimap/request_helpers.hpp" - -class PasswordHash { - public: - static bool check(const std::string& pass_crypt, - const std::string& pass_salt, - const std::string& candidate); - - static std::string base64decode(const std::string& s); - - private: - template - static std::string PBKDF2_HMAC_SHA_string(const std::string& pass, - const std::string& salt, - const uint iterations, - const uint outputBytes); - - static std::string md5_hash(const std::string& s); - - static bool is_valid_argon2(const std::string& pass_crypt, const std::string& candidate); -}; - -namespace basicauth { - std::optional authenticate_user(const request &req, data_selection& selection); - -} - -#endif diff --git a/include/cgimap/data_selection.hpp b/include/cgimap/data_selection.hpp index 88a76fab..0b410eba 100644 --- a/include/cgimap/data_selection.hpp +++ b/include/cgimap/data_selection.hpp @@ -172,11 +172,6 @@ class data_selection { // is user currently blocked? virtual bool is_user_blocked(const osm_user_id_t) = 0; - virtual bool get_user_id_pass(const std::string& display_name, - osm_user_id_t &, - std::string & pass_crypt, - std::string & pass_salt) = 0; - virtual std::set get_roles_for_user(osm_user_id_t id) = 0; virtual std::optional< osm_user_id_t > get_user_id_for_oauth2_token( diff --git a/include/cgimap/options.hpp b/include/cgimap/options.hpp index 070c1e41..14de1e2b 100644 --- a/include/cgimap/options.hpp +++ b/include/cgimap/options.hpp @@ -32,7 +32,6 @@ class global_settings_base { virtual int64_t get_scale() const = 0; virtual std::optional get_relation_max_members() const = 0; virtual std::optional get_element_max_tags() const = 0; - virtual bool get_basic_auth_support() const = 0; virtual uint32_t get_ratelimiter_ratelimit(bool) const = 0; virtual uint32_t get_ratelimiter_maxdebt(bool) const = 0; virtual bool get_ratelimiter_upload() const = 0; @@ -81,10 +80,6 @@ class global_settings_default : public global_settings_base { return {}; // default: unlimited } - bool get_basic_auth_support() const override { - return true; - } - uint32_t get_ratelimiter_ratelimit(bool moderator) const override { if (moderator) { return 1024 * 1024; // 1MB/s @@ -162,10 +157,6 @@ class global_settings_via_options : public global_settings_base { return m_element_max_tags; } - bool get_basic_auth_support() const override { - return m_basic_auth_support; - } - uint32_t get_ratelimiter_ratelimit(bool moderator) const override { if (moderator) { return m_moderator_ratelimiter_ratelimit; @@ -197,7 +188,6 @@ class global_settings_via_options : public global_settings_base { void set_scale(const po::variables_map &options); void set_relation_max_members(const po::variables_map &options); void set_element_max_tags(const po::variables_map &options); - void set_basic_auth_support(const po::variables_map &options); void set_ratelimiter_ratelimit(const po::variables_map &options); void set_ratelimiter_maxdebt(const po::variables_map &options); void set_ratelimiter_upload(const po::variables_map &options); @@ -213,7 +203,6 @@ class global_settings_via_options : public global_settings_base { int64_t m_scale; std::optional m_relation_max_members; std::optional m_element_max_tags; - bool m_basic_auth_support; uint32_t m_ratelimiter_ratelimit; uint32_t m_moderator_ratelimiter_ratelimit; uint32_t m_ratelimiter_maxdebt; @@ -258,9 +247,6 @@ class global_settings final { // Maximum number of tags for an OSM object (may be unlimited) static std::optional get_element_max_tags() { return settings->get_element_max_tags(); } - // Enable HTTP basic authentication support - static bool get_basic_auth_support() { return settings->get_basic_auth_support(); } - // average number of bytes/s to allow each client/moderator static uint32_t get_ratelimiter_ratelimit(bool moderator) { return settings->get_ratelimiter_ratelimit(moderator); } diff --git a/include/cgimap/process_request.hpp b/include/cgimap/process_request.hpp index e3a17989..c0ffe548 100644 --- a/include/cgimap/process_request.hpp +++ b/include/cgimap/process_request.hpp @@ -15,7 +15,6 @@ #include "cgimap/data_update.hpp" #include "cgimap/data_selection.hpp" #include "cgimap/routes.hpp" -#include "cgimap/basicauth.hpp" #include "cgimap/oauth2.hpp" #include diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34f67d2c..e9018646 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,6 @@ target_sources(cgimap_core PRIVATE http.cpp logger.cpp mime_types.cpp - basicauth.cpp oauth2.cpp options.cpp osm_responder.cpp @@ -77,7 +76,6 @@ target_link_libraries(cgimap_core ZLIB::ZLIB CryptoPP::CryptoPP Libmemcached::Libmemcached - Argon2::Argon2 $<$:Brotli::common> $<$:Brotli::encoder> $<$:Brotli::decoder> diff --git a/src/backend/apidb/readonly_pgsql_selection.cpp b/src/backend/apidb/readonly_pgsql_selection.cpp index 48f91214..b7fee916 100644 --- a/src/backend/apidb/readonly_pgsql_selection.cpp +++ b/src/backend/apidb/readonly_pgsql_selection.cpp @@ -794,42 +794,6 @@ bool readonly_pgsql_selection::is_user_blocked(const osm_user_id_t id) { return !res.empty(); } -bool readonly_pgsql_selection::get_user_id_pass(const std::string& user_name, osm_user_id_t & id, - std::string & pass_crypt, std::string & pass_salt) { - - std::string email = boost::algorithm::trim_copy(user_name); - - m.prepare("get_user_id_pass", - R"(SELECT id, pass_crypt, COALESCE(pass_salt, '') as pass_salt FROM users - WHERE (email = $1 OR display_name = $2) - AND (status = 'active' or status = 'confirmed') LIMIT 1 - )"); - - m.prepare("get_user_id_pass_case_insensitive", - R"(SELECT id, pass_crypt, COALESCE(pass_salt, '') as pass_salt FROM users - WHERE (LOWER(email) = LOWER($1) OR LOWER(display_name) = LOWER($2)) - AND (status = 'active' or status = 'confirmed') - )"); - - - auto res = m.exec_prepared("get_user_id_pass", email, user_name); - - if (res.empty()) { - // try case insensitive query - res = m.exec_prepared("get_user_id_pass_case_insensitive", email, user_name); - // failure, in case no entries or multiple entries were found - if (res.size() != 1) - return false; - } - - auto row = res[0]; - id = row["id"].as(); - pass_crypt = row["pass_crypt"].as(); - pass_salt = row["pass_salt"].as(); - - return true; -} - std::set< osm_user_role_t > readonly_pgsql_selection::get_roles_for_user(osm_user_id_t id) { std::set roles; diff --git a/src/basicauth.cpp b/src/basicauth.cpp deleted file mode 100644 index 29f2aa74..00000000 --- a/src/basicauth.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/** - * SPDX-License-Identifier: GPL-2.0-only - * - * This file is part of openstreetmap-cgimap (https://github.com/zerebubuth/openstreetmap-cgimap/). - * - * Copyright (C) 2009-2023 by the CGImap developer community. - * For a full list of authors see the git log. - */ - -#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "cgimap/basicauth.hpp" -#include "cgimap/options.hpp" - - -using namespace CryptoPP; - -bool PasswordHash::check(const std::string& pass_crypt, - const std::string& pass_salt, - const std::string& candidate) { - - std::string hashed_candidate; - - if (pass_salt.empty()) { - - if (is_valid_argon2(pass_crypt, candidate)) - return true; - - const auto digest = md5_hash(candidate); - return (boost::iequals(digest, pass_crypt)); - } - - std::vector params; // fields: algorithm, iterations, salt - boost::split(params, pass_salt, boost::is_any_of("!")); - - if (params.size() != 3) { - const auto digest = md5_hash(pass_salt + candidate); - return (boost::iequals(digest, pass_crypt)); - } - - const auto algorithm = params[0]; - const auto iterations = stoi(params[1]); - const auto salt = params[2]; - - const auto pass_crypt_decoded = base64decode(pass_crypt); - - if (algorithm == "sha512") - hashed_candidate = PBKDF2_HMAC_SHA_string( - candidate, salt, iterations, pass_crypt_decoded.size()); - else - throw std::runtime_error("Unknown hash algorithm"); - - return (hashed_candidate == pass_crypt); // both strings are base64 encoded -} - - -template -std::string PasswordHash::PBKDF2_HMAC_SHA_string(const std::string& pass, - const std::string& salt, - const uint iterations, - const uint outputBytes) { - - SecByteBlock result(outputBytes); - std::string base64Result; - - PKCS5_PBKDF2_HMAC pbkdf; - - pbkdf.DeriveKey(result, result.size(), 0x00, reinterpret_cast(pass.data()), - pass.size(), reinterpret_cast(salt.data()), salt.size(), iterations); - - ArraySource resultEncoder( - result, result.size(), true, - new Base64Encoder(new StringSink(base64Result), false)); - - return base64Result; -} - -std::string PasswordHash::md5_hash(const std::string& s) { - - Weak::MD5 hash; - std::string digest; - StringSource ss( - s, true, - new HashFilter(hash, new HexEncoder(new StringSink(digest), false))); - return digest; -} - -std::string PasswordHash::base64decode(const std::string& s) { - - std::string result; - StringSource ss(s, true, new Base64Decoder(new StringSink(result))); - return result; -} - -bool PasswordHash::is_valid_argon2(const std::string& pass_crypt, const std::string& candidate) -{ - // Argon2 public APIs don't support a secret (pepper) at this time without re-implementing parts of argon2, - // hence using argon2_verify without secret for the time being. - // Upstream issue: https://github.com/P-H-C/phc-winner-argon2/issues/314 - // Also assuming id algorithm as discussed in https://github.com/openstreetmap/openstreetmap-website/pull/3353 - - return (argon2_verify(pass_crypt.c_str(), candidate.c_str(), candidate.size(), Argon2_id) == ARGON2_OK); -} - - -namespace basicauth { - - [[nodiscard]] std::optional authenticate_user(const request &req, data_selection& selection) - { - - // Basic auth disabled in global configuration settings? - if (!(global_settings::get_basic_auth_support())) - return {}; - - std::string user_name; - std::string candidate; - - osm_user_id_t user_id; - std::string pass_crypt; - std::string pass_salt; - - const char * auth_hdr = req.get_param ("HTTP_AUTHORIZATION"); - if (auth_hdr == nullptr) - return {}; - - auto auth_header = std::string(auth_hdr); - - std::smatch sm; - - try { - std::regex r("[Bb][Aa][Ss][Ii][Cc] ([A-Za-z0-9\\+\\/]+=*).*"); - - if (!std::regex_match(auth_header, sm, r)) - return {}; - - if (sm.size() != 2) - return {}; - - } catch (std::regex_error&) { - return {}; - } - - std::string auth; - - try { - auth = PasswordHash::base64decode(sm[1]); - } catch (...) { - return {}; - } - - auto pos = auth.find(":"); - - if (pos == std::string::npos) - return {}; - - try { - user_name = auth.substr(0, pos); - candidate = auth.substr(pos + 1); - } catch (std::out_of_range&) { - return {}; - } - - if (user_name.empty() || candidate.empty()) - return {}; - - auto user_exists = selection.get_user_id_pass(user_name, user_id, pass_crypt, pass_salt); - - if (!user_exists) - throw http::unauthorized("Incorrect user or password"); - - if (PasswordHash::check(pass_crypt, pass_salt, candidate)) - return std::optional{user_id}; - else - throw http::unauthorized("Incorrect user or password"); - - } -} diff --git a/src/main.cpp b/src/main.cpp index 3abc587b..768bf3d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -134,7 +134,6 @@ void get_options(int argc, char **argv, po::variables_map &options) { ("scale", po::value(), "conversion factor from double lat/lon to internal int format") ("max-relation-members", po::value(), "max number of relation members per relation") ("max-element-tags", po::value(), "max number of tags per OSM element") - ("basic_auth_support", po::value(), "enable HTTP basic authentication support") ("ratelimit-upload", po::value(), "enable rate limiting for changeset upload") ; // clang-format on diff --git a/src/options.cpp b/src/options.cpp index 0e34bfee..b9c8a718 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -28,7 +28,6 @@ void global_settings_via_options::init_fallback_values(const global_settings_bas m_scale = def.get_scale(); m_relation_max_members = def.get_relation_max_members(); m_element_max_tags = def.get_element_max_tags(); - m_basic_auth_support = def.get_basic_auth_support(); m_ratelimiter_ratelimit = def.get_ratelimiter_ratelimit(false); m_moderator_ratelimiter_ratelimit = def.get_ratelimiter_ratelimit(true); m_ratelimiter_maxdebt = def.get_ratelimiter_maxdebt(false); @@ -48,7 +47,6 @@ void global_settings_via_options::set_new_options(const po::variables_map &optio set_scale(options); set_relation_max_members(options); set_element_max_tags(options); - set_basic_auth_support(options); set_ratelimiter_ratelimit(options); set_ratelimiter_maxdebt(options); set_ratelimiter_upload(options); @@ -141,12 +139,6 @@ void global_settings_via_options::set_element_max_tags(const po::variables_map & } } -void global_settings_via_options::set_basic_auth_support(const po::variables_map &options) { - if (options.count("basic_auth_support")) { - m_basic_auth_support = options["basic_auth_support"].as(); - } -} - void global_settings_via_options::set_ratelimiter_ratelimit(const po::variables_map &options) { if (options.count("ratelimit")) { auto parsed_bytes_per_sec = options["ratelimit"].as(); diff --git a/src/process_request.cpp b/src/process_request.cpp index 5973974d..9d56a1c4 100644 --- a/src/process_request.cpp +++ b/src/process_request.cpp @@ -416,17 +416,13 @@ bool show_redactions_requested(const request &req) { } -// Determine user id and allow_api_write flag based on Basic Auth or OAuth header +// Determine user id and allow_api_write flag based on OAuth header std::optional determine_user_id (const request& req, data_selection& selection, bool& allow_api_write) { - // Try to authenticate user via Basic Auth - std::optional user_id = basicauth::authenticate_user (req, selection); - // Try to authenticate user via OAuth2 Bearer Token - if (!user_id) - user_id = oauth2::validate_bearer_token (req, selection, allow_api_write); + std::optional user_id = oauth2::validate_bearer_token (req, selection, allow_api_write); return user_id; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e8d94081..b4ef5ffc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -58,24 +58,6 @@ if(BUILD_TESTING) COMMAND test_parse_id_list) - ################ - # test_basicauth - ################ - add_executable(test_basicauth - test_basicauth.cpp - test_request.cpp) - - target_link_libraries(test_basicauth - cgimap_common_compiler_options - cgimap_core - Boost::program_options - PQXX::PQXX - catch2) - - add_test(NAME test_basicauth - COMMAND test_basicauth) - - ########### # test_oauth2 ########### @@ -288,7 +270,6 @@ if(BUILD_TESTING) add_dependencies(check test_core test_parse_id_list - test_basicauth test_oauth2 test_http test_parse_time diff --git a/test/staticxml.cpp b/test/staticxml.cpp index 2c775017..741948e0 100644 --- a/test/staticxml.cpp +++ b/test/staticxml.cpp @@ -577,7 +577,6 @@ struct static_data_selection : public data_selection { bool supports_user_details() const override { return false; } bool is_user_blocked(const osm_user_id_t) override { return true; } - bool get_user_id_pass(const std::string&, osm_user_id_t &, std::string &, std::string &) override { return false; }; bool is_user_active(const osm_user_id_t) override { return true; } std::set get_roles_for_user(osm_user_id_t id) override { diff --git a/test/test_apidb_backend_changeset_uploads.cpp b/test/test_apidb_backend_changeset_uploads.cpp index c7e97014..dd6391b8 100644 --- a/test/test_apidb_backend_changeset_uploads.cpp +++ b/test/test_apidb_backend_changeset_uploads.cpp @@ -1945,7 +1945,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_message", "[changeset][u TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset][upload][db]" ) { - const std::string baseauth = "Basic ZGVtbzpwYXNzd29yZA=="; + const std::string bearertoken = "Bearer 4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8"; const std::string generator = "Test"; const std::optional none{}; @@ -1960,7 +1960,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset req.set_header("REQUEST_METHOD", "POST"); req.set_header("REQUEST_URI", "/api/0.6/changeset/1/upload"); req.set_header("REMOTE_ADDR", "127.0.0.1"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); // Prepare users, changesets SECTION("Initialize test data") { @@ -1968,10 +1968,8 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset tdb.run_sql(R"( INSERT INTO users (id, email, pass_crypt, pass_salt, creation_time, display_name, data_public, status) VALUES - (1, 'demo@example.com', '3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=', - 'sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=', - '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), - (2, 'user_2@example.com', '', '', '2013-11-14T02:10:00Z', 'user_2', false, 'active'); + (1, 'demo@example.com', 'x', '', '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), + (2, 'user_2@example.com', 'x', '', '2013-11-14T02:10:00Z', 'user_2', false, 'active'); INSERT INTO changesets (id, user_id, created_at, closed_at, num_changes) VALUES @@ -1984,7 +1982,13 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset INSERT INTO user_blocks (user_id, creator_id, reason, ends_at, needs_view) VALUES (1, 2, '', now() at time zone 'utc' - ('1 hour' ::interval), false); + + INSERT INTO oauth_applications (id, owner_type, owner_id, name, uid, secret, redirect_uri, scopes, confidential, created_at, updated_at) + VALUES (3, 'User', 1, 'App 1', 'dHKmvGkmuoMjqhCNmTJkf-EcnA61Up34O1vOHwTSvU8', '965136b8fb8d00e2faa2faaaed99c0ec10225518d0c8d9fb1d2af701e87eb68c', + 'http://demo.localhost:3000', 'write_api read_gpx', false, '2021-04-12 17:53:30', '2021-04-12 17:53:30'); + INSERT INTO public.oauth_access_tokens (id, resource_owner_id, application_id, token, refresh_token, expires_in, revoked_at, created_at, scopes, previous_refresh_token) + VALUES (67, 1, 3, '4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8', NULL, NULL, NULL, '2021-04-14 19:38:21', 'write_api', ''); )" ); } @@ -1992,7 +1996,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset SECTION("User providing wrong password"){ // set up request headers from test case - req.set_header("HTTP_AUTHORIZATION", "Basic ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); + req.set_header("HTTP_AUTHORIZATION", "Bearer ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); req.set_payload(R"( @@ -2005,6 +2009,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset REQUIRE(req.response_status() == 401); } +/* SECTION("User logging on with display name (different case)") { // set up request headers from test case @@ -2073,6 +2078,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset tdb.run_sql(R"(UPDATE users SET status = 'confirmed' where id = 1;)"); } +*/ SECTION("User is blocked (needs_view)") { @@ -2454,7 +2460,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changes new global_settings_enable_upload_rate_limiter_test_class()); global_settings::set_configuration(std::move(test_settings)); - const std::string baseauth = "Basic ZGVtbzpwYXNzd29yZA=="; + const std::string bearertoken = "Bearer 4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8"; const std::string generator = "Test"; auto sel_factory = tdb.get_data_selection_factory(); @@ -2468,9 +2474,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changes tdb.run_sql(R"( INSERT INTO users (id, email, pass_crypt, pass_salt, creation_time, display_name, data_public, status) VALUES - (1, 'demo@example.com', '3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=', - 'sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=', - '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), + (1, 'demo@example.com', 'xx', '', '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), (2, 'user_2@example.com', '', '', '2013-11-14T02:10:00Z', 'user_2', false, 'active'); INSERT INTO changesets (id, user_id, created_at, closed_at, num_changes) @@ -2485,6 +2489,13 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changes VALUES (1, 2, '', now() at time zone 'utc' - ('1 hour' ::interval), false); SELECT setval('current_nodes_id_seq', 14000000000, false); + + INSERT INTO oauth_applications (id, owner_type, owner_id, name, uid, secret, redirect_uri, scopes, confidential, created_at, updated_at) + VALUES (3, 'User', 1, 'App 1', 'dHKmvGkmuoMjqhCNmTJkf-EcnA61Up34O1vOHwTSvU8', '965136b8fb8d00e2faa2faaaed99c0ec10225518d0c8d9fb1d2af701e87eb68c', + 'http://demo.localhost:3000', 'write_api read_gpx', false, '2021-04-12 17:53:30', '2021-04-12 17:53:30'); + + INSERT INTO public.oauth_access_tokens (id, resource_owner_id, application_id, token, refresh_token, expires_in, revoked_at, created_at, scopes, previous_refresh_token) + VALUES (67, 1, 3, '4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8', NULL, NULL, NULL, '2021-04-14 19:38:21', 'write_api', ''); )" ); @@ -2525,7 +2536,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changes test_request req; req.set_header("REQUEST_METHOD", "POST"); req.set_header("REQUEST_URI", "/api/0.6/changeset/1/upload"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -2559,7 +2570,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changes test_request req; req.set_header("REQUEST_METHOD", "POST"); req.set_header("REQUEST_URI", "/api/0.6/changeset/1/upload"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); std::string nodes; diff --git a/test/test_apidb_backend_changesets.cpp b/test/test_apidb_backend_changesets.cpp index 0a6ea4e0..84b87ab3 100644 --- a/test/test_apidb_backend_changesets.cpp +++ b/test/test_apidb_backend_changesets.cpp @@ -88,6 +88,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_negative_changeset_ids", "[changes " (7, 90000000, 90000000, -1, true, '2016-04-16T15:09:00Z', 3229120632, 1); " ); + } SECTION("Validate data") { @@ -366,9 +367,8 @@ void init_changesets(test_database &tdb) { tdb.run_sql(R"( INSERT INTO users (id, email, pass_crypt, pass_salt, creation_time, display_name, data_public, status) VALUES - (31, 'demo@example.com', '$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg', - null, - '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), + (1, 'user_1@example.com', 'x', null, '2013-11-14T02:10:00Z', 'user_1', true, 'confirmed'), + (31, 'demo@example.com', 'x', null, '2013-11-14T02:10:00Z', 'demo', true, 'confirmed'), (32, 'user_2@example.com', '', '', '2013-11-14T02:10:00Z', 'user_2', false, 'active'); INSERT INTO changesets (id, user_id, created_at, closed_at, num_changes) @@ -389,6 +389,13 @@ void init_changesets(test_database &tdb) { INSERT INTO user_blocks (user_id, creator_id, reason, ends_at, needs_view) VALUES (31, 32, '', now() at time zone 'utc' - ('1 hour' ::interval), false); + INSERT INTO oauth_applications (id, owner_type, owner_id, name, uid, secret, redirect_uri, scopes, confidential, created_at, updated_at) + VALUES (3, 'User', 1, 'App 1', 'dHKmvGkmuoMjqhCNmTJkf-EcnA61Up34O1vOHwTSvU8', '965136b8fb8d00e2faa2faaaed99c0ec10225518d0c8d9fb1d2af701e87eb68c', + 'http://demo.localhost:3000', 'write_api read_gpx', false, '2021-04-12 17:53:30', '2021-04-12 17:53:30'); + + INSERT INTO public.oauth_access_tokens (id, resource_owner_id, application_id, token, refresh_token, expires_in, revoked_at, created_at, scopes, previous_refresh_token) + VALUES (67, 31, 3, '4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8', NULL, NULL, NULL, '2021-04-14 19:38:21', 'write_api', ''); + )" ); @@ -397,7 +404,7 @@ void init_changesets(test_database &tdb) { TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db]" ) { - const std::string baseauth = "Basic ZGVtbzpwYXNzd29yZA=="; + const std::string bearertoken = "Bearer 4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8"; const std::string generator = "Test"; auto sel_factory = tdb.get_data_selection_factory(); @@ -434,13 +441,13 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db REQUIRE(req.response_status() == 401); } - SECTION("User providing wrong password") + SECTION("User providing wrong bearer token") { // set up request headers from test case test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/create"); - req.set_header("HTTP_AUTHORIZATION", "Basic ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); + req.set_header("HTTP_AUTHORIZATION", "Bearer ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -466,7 +473,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/create"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -498,7 +505,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/create"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -532,7 +539,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/create"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -591,7 +598,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_create", "[changeset][db TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db]" ) { - const std::string baseauth = "Basic ZGVtbzpwYXNzd29yZA=="; + const std::string bearertoken = "Bearer 4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8"; const std::string generator = "Test"; auto sel_factory = tdb.get_data_selection_factory(); @@ -628,13 +635,13 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db } - SECTION("wrong user/password") + SECTION("wrong bearer token") { // set up request headers from test case test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/51"); - req.set_header("HTTP_AUTHORIZATION", "Basic ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); + req.set_header("HTTP_AUTHORIZATION", "Bearer ZGVtbzppbnZhbGlkcGFzc3dvcmQK"); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -659,7 +666,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/53"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -683,7 +690,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/666"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -706,7 +713,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/54"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -732,7 +739,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/56"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -762,7 +769,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/52"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); req.set_payload(R"( @@ -816,7 +823,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_update", "[changeset][db TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_close", "[changeset][db]" ) { - const std::string baseauth = "Basic ZGVtbzpwYXNzd29yZA=="; + const std::string bearertoken = "Bearer 4f41f2328befed5a33bcabdf14483081c8df996cbafc41e313417776e8fafae8"; const std::string generator = "Test"; auto sel_factory = tdb.get_data_selection_factory(); @@ -849,7 +856,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_close", "[changeset][db] test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/51/close"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); // execute the request @@ -865,7 +872,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_close", "[changeset][db] test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/53/close"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); // execute the request @@ -880,7 +887,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_close", "[changeset][db] test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/666/close"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); // execute the request @@ -895,7 +902,7 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_changeset_close", "[changeset][db] test_request req; req.set_header("REQUEST_METHOD", "PUT"); req.set_header("REQUEST_URI", "/api/0.6/changeset/54/close"); - req.set_header("HTTP_AUTHORIZATION", baseauth); + req.set_header("HTTP_AUTHORIZATION", bearertoken); req.set_header("REMOTE_ADDR", "127.0.0.1"); // execute the request diff --git a/test/test_basicauth.cpp b/test/test_basicauth.cpp deleted file mode 100644 index c6a6ee67..00000000 --- a/test/test_basicauth.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/** - * SPDX-License-Identifier: GPL-2.0-only - * - * This file is part of openstreetmap-cgimap (https://github.com/zerebubuth/openstreetmap-cgimap/). - * - * Copyright (C) 2009-2023 by the CGImap developer community. - * For a full list of authors see the git log. - */ - - -#include -#include -#include -#include - -#include "cgimap/basicauth.hpp" -#include "cgimap/options.hpp" -#include "test_request.hpp" -#include "test_empty_selection.hpp" - -#include "cgimap/backend/apidb/transaction_manager.hpp" - -#define CATCH_CONFIG_MAIN -#include - -namespace { - -class basicauth_test_data_selection : public empty_data_selection { -public: - - ~basicauth_test_data_selection() override = default; - - bool get_user_id_pass(const std::string& user_name, osm_user_id_t & user_id, - std::string & pass_crypt, std::string & pass_salt) override { - - if (user_name == "demo") { - user_id = 4711; - pass_crypt = "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg="; - pass_salt = "sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A="; - return true; - } - - if (user_name == "argon2") { - user_id = 4712; - pass_crypt = "$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg"; - pass_salt = ""; - return true; - } - - return false; - } - - struct factory : public data_selection::factory { - ~factory() override = default; - std::unique_ptr make_selection(Transaction_Owner_Base&) const override { - return std::make_unique(); - } - std::unique_ptr get_default_transaction() override { - return std::make_unique(); - } - }; -}; - -class global_settings_test_no_basic_auth : public global_settings_default { - -public: - - bool get_basic_auth_support() const override { - return false; - } -}; - -} // anonymous namespace - -TEST_CASE("test_md5_without_salt", "[basicauth]") { - CHECK(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "","password") == true); - CHECK(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "", "wrong") == false); -} - -TEST_CASE("test_md5_with_salt", "[basicauth]") { - CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "password") == true); - CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "wrong") == false); - CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "wrong","password") == false); -} - -TEST_CASE("test_pbkdf2_1000_32_sha512", "[basicauth]") { - CHECK(PasswordHash::check( - "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", - "sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=", - "password") == true); - - CHECK(PasswordHash::check( - "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", - "sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=", - "wrong") == false); - - CHECK(PasswordHash::check( - "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", - "sha512!1000!HR4z+hAvKV2ra1gwrongtoNzm/CNKe4cf7bPKwdUNrk=", - "password") == false); -} - - -TEST_CASE("test_pbkdf2_10000_32_sha512", "[basicauth]") { - - CHECK(PasswordHash::check( - "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", - "sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "password") == true); - - CHECK(PasswordHash::check( - "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", - "sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "wrong") == false); - - CHECK(PasswordHash::check( - "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", - "sha512!10000!OUQLgtMwronguvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "password") == false); -} - -TEST_CASE("test argon2", "[basicauth]") { - - CHECK(PasswordHash::check( - "$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg", - "", - "password") == true); - - CHECK(PasswordHash::check( - "$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg", - "", - "wrong") == false); -} - - -TEST_CASE("test_authenticate_user", "[basicauth]") { - - auto factory = std::make_shared(); - auto txn_readonly = factory->get_default_transaction(); - auto sel = factory->make_selection(*txn_readonly); - test_request req; - - SECTION("Missing Header") { - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("Empty AUTH header"){ - req.set_header("HTTP_AUTHORIZATION",""); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("Empty AUTH header"){ - req.set_header("HTTP_AUTHORIZATION","Basic "); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("User without password"){ - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbw=="); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("User and colon without password"){ - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzo="); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("Known user with correct password"){ - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzpwYXNzd29yZA=="); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{4711}); - } - - SECTION("Known user with correct password, argon2") { - req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOnBhc3N3b3Jk"); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{4712}); - } - - SECTION("Crap data") { - req.set_header("HTTP_AUTHORIZATION","Basic TotalCrapData=="); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } - - SECTION("Test with known user and incorrect password") { - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzppbmNvcnJlY3Q="); - REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); - } - - SECTION("Test with known user and incorrect password, argon2") { - req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOndyb25n"); - REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); - } - - SECTION("Test with unknown user and incorrect password") { - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzI6aW5jb3JyZWN0"); - REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); - } - - SECTION("Known user with correct password; basicauth disabled in config") { - auto test_settings = std::unique_ptr(new global_settings_test_no_basic_auth()); - global_settings::set_configuration(std::move(test_settings)); - req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzpwYXNzd29yZA=="); - auto res = basicauth::authenticate_user(req, *sel); - CHECK(res == std::optional{}); - } -} - diff --git a/test/test_empty_selection.hpp b/test/test_empty_selection.hpp index 5febf772..39ebe385 100644 --- a/test/test_empty_selection.hpp +++ b/test/test_empty_selection.hpp @@ -52,7 +52,6 @@ class empty_data_selection : public data_selection { bool supports_user_details() const override { return false; } bool is_user_blocked(const osm_user_id_t) override { return true; } - bool get_user_id_pass(const std::string&, osm_user_id_t &, std::string &, std::string &) override { return false; }; std::set get_roles_for_user(osm_user_id_t id) override { return {}; } std::optional< osm_user_id_t > get_user_id_for_oauth2_token( const std::string &token_id, bool &expired, bool &revoked, diff --git a/test/test_parse_options.cpp b/test/test_parse_options.cpp index 9af75dad..2528dbf3 100644 --- a/test/test_parse_options.cpp +++ b/test/test_parse_options.cpp @@ -49,7 +49,6 @@ TEST_CASE("Set all supported options" "[options]") { vm.emplace("max-way-nodes", po::variable_value((int) 200, false)); vm.emplace("max-relation-members", po::variable_value((int) 50, false)); vm.emplace("max-element-tags", po::variable_value((int) 10, false)); - vm.emplace("basic_auth_support", po::variable_value(false, false)); vm.emplace("ratelimit", po::variable_value((long) 1000000, false)); vm.emplace("moderator-ratelimit", po::variable_value((long) 10000000, false)); vm.emplace("maxdebt", po::variable_value((long) 500, false)); @@ -67,7 +66,6 @@ TEST_CASE("Set all supported options" "[options]") { REQUIRE( global_settings::get_scale() == 100 ); REQUIRE( global_settings::get_relation_max_members() == 50 ); REQUIRE( global_settings::get_element_max_tags() == 10 ); - REQUIRE( global_settings::get_basic_auth_support() == false ); REQUIRE( global_settings::get_ratelimiter_ratelimit(false) == 1000000 ); REQUIRE( global_settings::get_ratelimiter_maxdebt(false) == 500l * 1024 * 1024 ); REQUIRE( global_settings::get_ratelimiter_ratelimit(true) == 10000000 );