Skip to content

Commit

Permalink
Adding support for Argon2 for password hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
mmd-osm committed Nov 4, 2021
1 parent d7ab151 commit 3dc8e7b
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 42 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ RUN apt-get update -qq && \
libfcgi-dev libxml2-dev libmemcached-dev \
libboost-program-options-dev libboost-system-dev \
libboost-filesystem-dev libboost-locale-dev libcrypto++-dev libyajl-dev \
libpqxx-dev zlib1g-dev \
libpqxx-dev zlib1g-dev libargon2-dev \
postgresql-12 postgresql-server-dev-all \
--no-install-recommends && \
apt-get clean && \
Expand All @@ -31,7 +31,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 \
libxml2 libcrypto++6 libyajl2 libpqxx-6.4 zlib1g argon2 \
--no-install-recommends && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
Expand Down
3 changes: 2 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ development are in brackets. Respective library versions for Ubuntu 18.04 and Ub
* libboost (1.58.0+dfsg-5ubuntu3.1)
* libcrypto++ (5.6.1-9)
* zlib1g-dev (1:1.2.11.dfsg-0ubuntu2)
* libargon2-dev

If you're running a Debian or Ubuntu system these can be installed
using the following command:

sudo apt-get install libxml2-dev libpqxx-dev libfcgi-dev zlib1g-dev \
libboost-dev libboost-program-options-dev libboost-filesystem-dev \
libboost-system-dev libboost-locale-dev libmemcached-dev \
libcrypto++-dev
libcrypto++-dev libargon2-dev

Note that C++11 is _required_ to build CGImap.

Expand Down
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ PKG_CHECK_MODULES(LIBPQXX, libpqxx >= 4.0)
AC_SUBST(LIBPQXX_CFLAGS)
AC_SUBST(LIBPQXX_LIBS)

PKG_CHECK_MODULES([ARGON2], [libargon2])
AC_SUBST(argon2_lib, [", libargon2"])

#m4_include([aclocal/ax_boost_base.m4])
#m4_include([aclocal/ax_boost_system.m4])
#m4_include([aclocal/ax_boost_program_options.m4])
Expand Down
10 changes: 6 additions & 4 deletions include/cgimap/basicauth.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@

class PasswordHash {
public:
bool check(const std::string& pass_crypt,
static bool check(const std::string& pass_crypt,
const std::string& pass_salt,
const std::string& candidate);

std::string base64decode(const std::string& s);
static std::string base64decode(const std::string& s);

private:
template <class T>
std::string PBKDF2_HMAC_SHA_string(const std::string& pass,
static std::string PBKDF2_HMAC_SHA_string(const std::string& pass,
const std::string& salt,
const uint iterations,
const uint outputBytes);

std::string md5_hash(const std::string& s);
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 {
Expand Down
30 changes: 15 additions & 15 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,26 @@ ___test_test_apidb_backend_changesets_LDADD+=libcgimap_staticxml.la
___test_test_apidb_backend_changeset_downloads_LDADD+=libcgimap_staticxml.la
endif

___openstreetmap_cgimap_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_SYSTEM_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_core_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @CRYPTOPP_LIBS@
___openstreetmap_cgimap_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_SYSTEM_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_core_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
check_PROGRAMS+=../test/test_parse_id_list ../test/test_basicauth ../test/test_oauth ../test/test_oauth2 ../test/test_http ../test/test_parse_time ../test/test_parse_osmchange_input ../test/test_parse_changeset_input
___test_test_parse_id_list_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_basicauth_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_oauth_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_oauth2_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_http_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_parse_id_list_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_basicauth_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_oauth_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_oauth2_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_http_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_parse_time_LDADD=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @LIBPQXX_LIBS@
___test_test_parse_osmchange_input_LDADD=libcgimap_core.la @LIBXML_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
___test_test_parse_changeset_input_LDADD=libcgimap_core.la @LIBXML_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@

if ENABLE_APIDB
___test_test_apidb_backend_nodes_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_oauth_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_oauth2_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_historic_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_changesets_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_changeset_downloads_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_changeset_uploads_LDADD+=libcgimap_core.la @LIBXML_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@
___test_test_apidb_backend_nodes_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_oauth_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_oauth2_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_historic_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_changesets_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_changeset_downloads_LDADD+=libcgimap_core.la @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
___test_test_apidb_backend_changeset_uploads_LDADD+=libcgimap_core.la @LIBXML_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @LIBPQXX_LIBS@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@
endif

################################################################################
Expand Down Expand Up @@ -173,7 +173,7 @@ libcgimap_core_la_SOURCES=\
xml_formatter.cpp \
xml_writer.cpp \
zlib.cpp
libcgimap_core_la_LIBADD=@LIBXML_LIBS@ @YAJL_LIBS@ @LIBMEMCACHED_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @CRYPTOPP_LIBS@
libcgimap_core_la_LIBADD=@LIBXML_LIBS@ @YAJL_LIBS@ @LIBMEMCACHED_LIBS@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_LOCALE_LIB@ @CRYPTOPP_LIBS@ @ARGON2_LIBS@

libcgimap_core_la_SOURCES+=\
parsers/exception.cpp \
Expand Down
4 changes: 2 additions & 2 deletions src/backend/apidb/readonly_pgsql_selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,13 +745,13 @@ bool readonly_pgsql_selection::get_user_id_pass(const std::string& user_name, os
std::string email = boost::algorithm::trim_copy(user_name);

m.prepare("get_user_id_pass",
R"(SELECT id, pass_crypt, pass_salt FROM users
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, pass_salt FROM users
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')
)");
Expand Down
20 changes: 18 additions & 2 deletions src/basicauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
#include <cryptopp/secblock.h>
#include <cryptopp/sha.h>
#include <sys/types.h>
#include <argon2.h>
#include <cassert>
#include <iostream>
#include <regex>
#include <string>

#include <boost/algorithm/string.hpp>


#include "cgimap/basicauth.hpp"


Expand All @@ -28,6 +30,10 @@ bool PasswordHash::check(const std::string& pass_crypt,
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));
}
Expand Down Expand Up @@ -94,6 +100,16 @@ std::string PasswordHash::base64decode(const std::string& s) {
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 {

Expand Down Expand Up @@ -132,7 +148,7 @@ namespace basicauth {
std::string auth;

try {
auth = pwd_hash.base64decode(sm[1]);
auth = PasswordHash::base64decode(sm[1]);
} catch (...) {
return boost::optional<osm_user_id_t>{};
}
Expand All @@ -157,7 +173,7 @@ namespace basicauth {
if (!user_exists)
throw http::unauthorized("Incorrect user or password");

if (pwd_hash.check(pass_crypt, pass_salt, candidate))
if (PasswordHash::check(pass_crypt, pass_salt, candidate))
return boost::optional<osm_user_id_t>{user_id};
else
throw http::unauthorized("Incorrect user or password");
Expand Down
11 changes: 9 additions & 2 deletions test/test_apidb_backend_changesets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,18 @@ void init_changesets(test_database &tdb) {

// Prepare users, changesets

// Note: previously used credentials for user id 31:
//
// pass_crypt: '3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg='
// pass_salt: 'sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A='
//
// Those are still being used in test_apidb_backend_changeset_uploads.cpp

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', '3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=',
'sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=',
(31, 'demo@example.com', '$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg',
null,
'2013-11-14T02:10:00Z', 'demo', true, 'confirmed'),
(32, 'user_2@example.com', '', '', '2013-11-14T02:10:00Z', 'user_2', false, 'active');
Expand Down
65 changes: 51 additions & 14 deletions test/test_basicauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ class basicauth_test_data_selection
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;
}

Expand All @@ -128,56 +135,65 @@ class basicauth_test_data_selection

void test_password_hash() {

PasswordHash pwd_hash;

// test_md5_without_salt
assert_equal<bool>(pwd_hash.check("5f4dcc3b5aa765d61d8327deb882cf99", "",
assert_equal<bool>(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "",
"password"), true);

assert_equal<bool>(pwd_hash.check("5f4dcc3b5aa765d61d8327deb882cf99", "", "wrong"), false);
assert_equal<bool>(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "", "wrong"), false);

// test_md5_with_salt
assert_equal<bool>(pwd_hash.check("67a1e09bb1f83f5007dc119c14d663aa", "salt",
assert_equal<bool>(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt",
"password"), true);
assert_equal<bool>(pwd_hash.check("67a1e09bb1f83f5007dc119c14d663aa", "salt",
assert_equal<bool>(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt",
"wrong"), false);
assert_equal<bool>(pwd_hash.check("67a1e09bb1f83f5007dc119c14d663aa", "wrong",
assert_equal<bool>(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "wrong",
"password"), false);

// test_pbkdf2_1000_32_sha512
assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=",
"sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=",
"password"), true);

assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=",
"sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=",
"wrong"), false);

assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=",
"sha512!1000!HR4z+hAvKV2ra1gwrongtoNzm/CNKe4cf7bPKwdUNrk=",
"password"), false);

// test_pbkdf2_10000_32_sha512
assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=",
"sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=",
"password"), true);

assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=",
"sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=",
"wrong"), false);

assert_equal<bool>(pwd_hash.check(
assert_equal<bool>(PasswordHash::check(
"3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=",
"sha512!10000!OUQLgtMwronguvanFT5/WtWaCwdOdrir8QOtFwxhO0A=",
"password"), false);

// test argon2
assert_equal<bool>(PasswordHash::check(
"$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg",
"",
"password"), true);

assert_equal<bool>(PasswordHash::check(
"$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg",
"",
"wrong"), false);
}


void test_authenticate_user() {

std::shared_ptr<data_selection::factory> factory =
Expand Down Expand Up @@ -227,6 +243,13 @@ void test_authenticate_user() {
assert_equal<boost::optional<osm_user_id_t> >(res, boost::optional<osm_user_id_t>{4711}, "Known user with correct password");
}

{
test_request req;
req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOnBhc3N3b3Jk");
auto res = basicauth::authenticate_user(req, sel);
assert_equal<boost::optional<osm_user_id_t> >(res, boost::optional<osm_user_id_t>{4712}, "Known user with correct password, argon2");
}

{
test_request req;
req.set_header("HTTP_AUTHORIZATION","Basic TotalCrapData==");
Expand All @@ -249,6 +272,21 @@ void test_authenticate_user() {
}
}

// Test with known user and incorrect password, argon2
{
test_request req;
req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOndyb25n");
try {
auto res = basicauth::authenticate_user(req, sel);
throw std::runtime_error("Known user, incorrect password: expected http unauthorized exception");

} catch (http::exception &e) {
if (e.code() != 401)
throw std::runtime_error(
"Known user / incorrect password: Expected HTTP 401");
}
}

// Test with unknown user and incorrect password
{
test_request req;
Expand All @@ -272,7 +310,6 @@ int main() {
ANNOTATE_EXCEPTION(test_password_hash());
ANNOTATE_EXCEPTION(test_authenticate_user());


} catch (const std::exception &e) {
std::cerr << "EXCEPTION: " << e.what() << std::endl;
return 1;
Expand Down

0 comments on commit 3dc8e7b

Please # to comment.