2021-01-25 00:24:31 +01:00
|
|
|
#include "./authentication.h"
|
|
|
|
|
|
|
|
#include "./helper.h"
|
|
|
|
#include "./serversetup.h"
|
|
|
|
|
|
|
|
#include <c++utilities/conversion/stringconversion.h>
|
|
|
|
#include <c++utilities/io/ansiescapecodes.h>
|
|
|
|
|
|
|
|
#include <openssl/sha.h>
|
|
|
|
|
|
|
|
namespace LibRepoMgr {
|
|
|
|
|
|
|
|
template <> inline void convertValue(const std::multimap<std::string, std::string> &multimap, const std::string &key, UserPermissions &result)
|
|
|
|
{
|
|
|
|
using namespace std;
|
|
|
|
using namespace CppUtilities::EscapeCodes;
|
|
|
|
|
|
|
|
const auto value = getLastValueSv(multimap, key);
|
|
|
|
if (!value.has_value()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = UserPermissions::None;
|
|
|
|
const auto parts = CppUtilities::splitStringSimple<std::vector<std::string_view>>(value.value(), " "sv);
|
|
|
|
for (const auto &part : parts) {
|
|
|
|
if (part.empty()) {
|
|
|
|
} else if (part == "read_build_actions_details") {
|
|
|
|
result = result | UserPermissions::ReadBuildActionsDetails;
|
2022-03-10 23:19:02 +01:00
|
|
|
} else if (part == "download_artefacts") {
|
|
|
|
result = result | UserPermissions::DownloadArtefacts;
|
2021-01-25 00:24:31 +01:00
|
|
|
} else if (part == "modify_build_actions") {
|
|
|
|
result = result | UserPermissions::ModifyBuildActions;
|
|
|
|
} else if (part == "perform_admin_actions") {
|
|
|
|
result = result | UserPermissions::PerformAdminActions;
|
|
|
|
} else {
|
|
|
|
std::cerr << Phrases::Error << "Specified permission \"" << part << "\" for key \"" << key << "\" is invalid." << Phrases::End;
|
|
|
|
std::exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServiceSetup::Authentication::applyConfig(const std::string &userName, const std::multimap<std::string, std::string> &multimap)
|
|
|
|
{
|
|
|
|
auto &user = users[userName];
|
|
|
|
convertValue(multimap, "password_sha512", user.passwordSha512);
|
|
|
|
convertValue(multimap, "permissions", user.permissions);
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr char toLower(const char c)
|
|
|
|
{
|
|
|
|
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
|
|
|
|
}
|
|
|
|
|
2022-07-10 17:18:29 +02:00
|
|
|
UserAuth ServiceSetup::Authentication::authenticate(std::string_view authorizationHeader) const
|
2021-01-25 00:24:31 +01:00
|
|
|
{
|
|
|
|
// extract user name and password from base64 encoded header value
|
2022-07-10 17:18:29 +02:00
|
|
|
auto auth = UserAuth();
|
2021-01-25 00:24:31 +01:00
|
|
|
if (!CppUtilities::startsWith(authorizationHeader, "Basic ") && authorizationHeader.size() < 100) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t> data;
|
|
|
|
try {
|
|
|
|
data = CppUtilities::decodeBase64(authorizationHeader.data() + 6, static_cast<std::uint32_t>(authorizationHeader.size() - 6));
|
|
|
|
} catch (const CppUtilities::ConversionException &) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
const auto parts = CppUtilities::splitStringSimple<std::vector<std::string_view>>(
|
|
|
|
std::string_view(reinterpret_cast<const char *>(data.first.get()), data.second), ":", 2);
|
|
|
|
if (parts.size() != 2) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// find relevant user
|
|
|
|
const std::string_view userName = parts[0], password = parts[1];
|
|
|
|
if (userName.empty() || password.empty()) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
if (userName == "try" && password == "again") {
|
2022-07-10 17:18:29 +02:00
|
|
|
auth.permissions = UserPermissions::TryAgain;
|
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
const auto user = users.find(std::string(userName));
|
|
|
|
if (user == users.cend()) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
constexpr auto sha512HexSize = 128;
|
|
|
|
if (user->second.passwordSha512.size() != sha512HexSize) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// hash password
|
|
|
|
unsigned char hash[SHA512_DIGEST_LENGTH];
|
2022-11-03 22:34:31 +01:00
|
|
|
SHA512(reinterpret_cast<const unsigned char *>(password.data()), password.size(), hash);
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
// check whether password hash matches
|
|
|
|
auto i = user->second.passwordSha512.cbegin();
|
|
|
|
for (unsigned char hashNumber : hash) {
|
|
|
|
const auto digits = CppUtilities::numberToString(hashNumber, 16);
|
|
|
|
if ((toLower(*(i++)) != toLower(digits.size() < 2 ? '0' : digits.front())) || (toLower(*(i++)) != toLower(digits.back()))) {
|
2022-07-10 17:18:29 +02:00
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the user's permissions
|
2022-07-10 17:18:29 +02:00
|
|
|
auth.permissions = user->second.permissions;
|
|
|
|
auth.name = userName;
|
|
|
|
auth.password = password;
|
|
|
|
return auth;
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace LibRepoMgr
|