Auto reformatted the base, ref #470

This commit is contained in:
emeric
2024-05-24 23:31:52 +02:00
parent 83b868673c
commit 39941d90a3
460 changed files with 8583 additions and 8514 deletions
@@ -19,11 +19,10 @@
#include "AuthServiceBase.hpp"
#include <cstdlib>
#include "core/ILogger.hpp"
#include "database/Db.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "core/ILogger.hpp"
namespace lms::auth
{
@@ -31,7 +30,8 @@ namespace lms::auth
AuthServiceBase::AuthServiceBase(Db& db)
: _db{ db }
{}
{
}
UserId AuthServiceBase::getOrCreateUser(std::string_view loginName)
{
@@ -91,4 +91,4 @@ namespace lms::auth
{
return _db.getTLSSession();
}
}
} // namespace lms::auth
@@ -20,13 +20,14 @@
#pragma once
#include <string_view>
#include "database/UserId.hpp"
namespace lms::db
{
class Db;
class Session;
}
} // namespace lms::db
namespace lms::auth
{
@@ -35,12 +36,12 @@ namespace lms::auth
protected:
AuthServiceBase(db::Db& db);
db::UserId getOrCreateUser(std::string_view loginName);
void onUserAuthenticated(db::UserId userId);
db::UserId getOrCreateUser(std::string_view loginName);
void onUserAuthenticated(db::UserId userId);
db::Session& getDbSession();
db::Session& getDbSession();
private:
db::Db& _db;
};
}
} // namespace lms::auth
@@ -23,121 +23,121 @@
#include <Wt/Auth/PasswordStrengthValidator.h>
#include <Wt/WRandom.h>
#include "services/auth/Types.hpp"
#include "core/Exception.hpp"
#include "core/ILogger.hpp"
#include "database/AuthToken.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "core/Exception.hpp"
#include "core/ILogger.hpp"
#include "services/auth/Types.hpp"
namespace lms::auth
{
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
{
return std::make_unique<AuthTokenService>(db, maxThrottlerEntries);
}
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
{
return std::make_unique<AuthTokenService>(db, maxThrottlerEntries);
}
static const Wt::Auth::SHA1HashFunction sha1Function;
static const Wt::Auth::SHA1HashFunction sha1Function;
AuthTokenService::AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
: AuthServiceBase {db}
, _loginThrottler {maxThrottlerEntries}
{
}
AuthTokenService::AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
: AuthServiceBase{ db }
, _loginThrottler{ maxThrottlerEntries }
{
}
std::string
AuthTokenService::createAuthToken(db::UserId userId, const Wt::WDateTime& expiry)
{
const std::string secret {Wt::WRandom::generateId(32)};
const std::string secretHash {sha1Function.compute(secret, {})};
std::string
AuthTokenService::createAuthToken(db::UserId userId, const Wt::WDateTime& expiry)
{
const std::string secret{ Wt::WRandom::generateId(32) };
const std::string secretHash{ sha1Function.compute(secret, {}) };
db::Session& session {getDbSession()};
db::Session& session{ getDbSession() };
auto transaction {session.createWriteTransaction()};
auto transaction{ session.createWriteTransaction() };
db::User::pointer user {db::User::find(session, userId)};
if (!user)
throw Exception {"User deleted"};
db::User::pointer user{ db::User::find(session, userId) };
if (!user)
throw Exception{ "User deleted" };
db::AuthToken::pointer authToken {session.create<db::AuthToken>(secretHash, expiry, user)};
db::AuthToken::pointer authToken{ session.create<db::AuthToken>(secretHash, expiry, user) };
LMS_LOG(UI, DEBUG, "Created auth token for user '" << user->getLoginName() << "', expiry = " << expiry.toString());
LMS_LOG(UI, DEBUG, "Created auth token for user '" << user->getLoginName() << "', expiry = " << expiry.toString());
if (user->getAuthTokensCount() >= 50)
db::AuthToken::removeExpiredTokens(session, Wt::WDateTime::currentDateTime());
if (user->getAuthTokensCount() >= 50)
db::AuthToken::removeExpiredTokens(session, Wt::WDateTime::currentDateTime());
return secret;
}
return secret;
}
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo>
AuthTokenService::processAuthToken(std::string_view secret)
{
const std::string secretHash {sha1Function.compute(std::string {secret}, {})};
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo>
AuthTokenService::processAuthToken(std::string_view secret)
{
const std::string secretHash{ sha1Function.compute(std::string{ secret }, {}) };
db::Session& session {getDbSession()};
auto transaction {session.createWriteTransaction()};
db::Session& session{ getDbSession() };
auto transaction{ session.createWriteTransaction() };
db::AuthToken::pointer authToken {db::AuthToken::find(session, secretHash)};
if (!authToken)
return std::nullopt;
db::AuthToken::pointer authToken{ db::AuthToken::find(session, secretHash) };
if (!authToken)
return std::nullopt;
if (authToken->getExpiry() < Wt::WDateTime::currentDateTime())
{
authToken.remove();
return std::nullopt;
}
if (authToken->getExpiry() < Wt::WDateTime::currentDateTime())
{
authToken.remove();
return std::nullopt;
}
LMS_LOG(UI, DEBUG, "Found auth token for user '" << authToken->getUser()->getLoginName() << "'!");
LMS_LOG(UI, DEBUG, "Found auth token for user '" << authToken->getUser()->getLoginName() << "'!");
AuthTokenService::AuthTokenProcessResult::AuthTokenInfo res {authToken->getUser()->getId(), authToken->getExpiry()};
authToken.remove();
AuthTokenService::AuthTokenProcessResult::AuthTokenInfo res{ authToken->getUser()->getId(), authToken->getExpiry() };
authToken.remove();
return res;
}
return res;
}
AuthTokenService::AuthTokenProcessResult
AuthTokenService::processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue)
{
// Do not waste too much resource on brute force attacks (optim)
{
std::shared_lock lock {_mutex};
AuthTokenService::AuthTokenProcessResult
AuthTokenService::processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue)
{
// Do not waste too much resource on brute force attacks (optim)
{
std::shared_lock lock{ _mutex };
if (_loginThrottler.isClientThrottled(clientAddress))
return AuthTokenProcessResult {AuthTokenProcessResult::State::Throttled};
}
if (_loginThrottler.isClientThrottled(clientAddress))
return AuthTokenProcessResult{ AuthTokenProcessResult::State::Throttled };
}
auto res {processAuthToken(tokenValue)};
{
std::unique_lock lock {_mutex};
auto res{ processAuthToken(tokenValue) };
{
std::unique_lock lock{ _mutex };
if (_loginThrottler.isClientThrottled(clientAddress))
return AuthTokenProcessResult {AuthTokenProcessResult::State::Throttled};
if (_loginThrottler.isClientThrottled(clientAddress))
return AuthTokenProcessResult{ AuthTokenProcessResult::State::Throttled };
if (!res)
{
_loginThrottler.onBadClientAttempt(clientAddress);
return AuthTokenProcessResult {AuthTokenProcessResult::State::Denied};
}
if (!res)
{
_loginThrottler.onBadClientAttempt(clientAddress);
return AuthTokenProcessResult{ AuthTokenProcessResult::State::Denied };
}
_loginThrottler.onGoodClientAttempt(clientAddress);
onUserAuthenticated(res->userId);
return AuthTokenProcessResult {AuthTokenProcessResult::State::Granted, std::move(*res)};
}
}
_loginThrottler.onGoodClientAttempt(clientAddress);
onUserAuthenticated(res->userId);
return AuthTokenProcessResult{ AuthTokenProcessResult::State::Granted, std::move(*res) };
}
}
void
AuthTokenService::clearAuthTokens(db::UserId userId)
{
db::Session& session {getDbSession()};
void
AuthTokenService::clearAuthTokens(db::UserId userId)
{
db::Session& session{ getDbSession() };
auto transaction {session.createWriteTransaction()};
auto transaction{ session.createWriteTransaction() };
db::User::pointer user {db::User::find(session, userId)};
if (!user)
throw Exception {"User deleted"};
db::User::pointer user{ db::User::find(session, userId) };
if (!user)
throw Exception{ "User deleted" };
user.modify()->clearAuthTokens();
}
user.modify()->clearAuthTokens();
}
} // namespace lms::auth
@@ -22,34 +22,35 @@
#include <shared_mutex>
#include "services/auth/IAuthTokenService.hpp"
#include "AuthServiceBase.hpp"
#include "LoginThrottler.hpp"
namespace lms::db
{
class Session;
class Session;
}
namespace lms::auth
{
class AuthTokenService : public IAuthTokenService, public AuthServiceBase
{
public:
AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries);
class AuthTokenService : public IAuthTokenService, public AuthServiceBase
{
public:
AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries);
AuthTokenService(const AuthTokenService&) = delete;
AuthTokenService& operator=(const AuthTokenService&) = delete;
AuthTokenService(AuthTokenService&&) = delete;
AuthTokenService& operator=(AuthTokenService&&) = delete;
AuthTokenService(const AuthTokenService&) = delete;
AuthTokenService& operator=(const AuthTokenService&) = delete;
AuthTokenService(AuthTokenService&&) = delete;
AuthTokenService& operator=(AuthTokenService&&) = delete;
private:
AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) override;
std::string createAuthToken(db::UserId userId, const Wt::WDateTime& expiry) override;
void clearAuthTokens(db::UserId userId) override;
private:
AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) override;
std::string createAuthToken(db::UserId userId, const Wt::WDateTime& expiry) override;
void clearAuthTokens(db::UserId userId) override;
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo> processAuthToken(std::string_view secret);
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo> processAuthToken(std::string_view secret);
std::shared_mutex _mutex;
LoginThrottler _loginThrottler;
};
}
std::shared_mutex _mutex;
LoginThrottler _loginThrottler;
};
} // namespace lms::auth
+9 -8
View File
@@ -20,16 +20,17 @@
#include "services/auth/IEnvService.hpp"
#include "services/auth/Types.hpp"
#include "http-headers/HttpHeadersEnvService.hpp"
namespace lms::auth
{
std::unique_ptr<IEnvService>
createEnvService(std::string_view backendName, db::Db& db)
{
if (backendName == "http-headers")
return std::make_unique<HttpHeadersEnvService>(db);
std::unique_ptr<IEnvService>
createEnvService(std::string_view backendName, db::Db& db)
{
if (backendName == "http-headers")
return std::make_unique<HttpHeadersEnvService>(db);
throw Exception {"Authentication backend '" + std::string {backendName} + "' is not supported!"};
}
}
throw Exception{ "Authentication backend '" + std::string{ backendName } + "' is not supported!" };
}
} // namespace lms::auth
@@ -17,8 +17,6 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
/* This file contains some classes in order to get info from file using the libavconv */
#include "LoginThrottler.hpp"
#include "core/ILogger.hpp"
@@ -44,13 +42,13 @@ namespace lms::auth
{
return address.is_v6() ? getAddressWithMask(address.to_v6(), 64) : address;
}
}
} // namespace
void LoginThrottler::removeOutdatedEntries()
{
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
for (auto it{ std::begin(_attemptsInfo) }; it != std::end(_attemptsInfo); )
for (auto it{ std::begin(_attemptsInfo) }; it != std::end(_attemptsInfo);)
{
if (it->second.nextAttempt <= now)
it = _attemptsInfo.erase(it);
@@ -110,4 +108,4 @@ namespace lms::auth
return it->second.nextAttempt > Wt::WDateTime::currentDateTime();
}
}
} // namespace lms::auth
+23 -23
View File
@@ -24,34 +24,34 @@
#include <Wt/WDateTime.h>
#include "core/NetAddress.hpp"
#include "core/Exception.hpp"
#include "core/NetAddress.hpp"
namespace lms::auth
{
class LoginThrottler
{
public:
LoginThrottler(std::size_t maxEntries) : _maxEntries {maxEntries} {}
class LoginThrottler
{
public:
LoginThrottler(std::size_t maxEntries)
: _maxEntries{ maxEntries } {}
// user must lock these calls to avoid races
bool isClientThrottled(const boost::asio::ip::address& address) const;
void onBadClientAttempt(const boost::asio::ip::address& address);
void onGoodClientAttempt(const boost::asio::ip::address& address);
// user must lock these calls to avoid races
bool isClientThrottled(const boost::asio::ip::address& address) const;
void onBadClientAttempt(const boost::asio::ip::address& address);
void onGoodClientAttempt(const boost::asio::ip::address& address);
private:
void removeOutdatedEntries();
private:
void removeOutdatedEntries();
const std::size_t _maxEntries;
static constexpr std::size_t _maxBadConsecutiveAttemptCount {5};
static constexpr std::chrono::seconds _throttlingDuration {3};
struct AttemptInfo
{
Wt::WDateTime nextAttempt;
std::size_t badConsecutiveAttemptCount{};
};
std::unordered_map<boost::asio::ip::address, AttemptInfo> _attemptsInfo;
};
} // Auth
const std::size_t _maxEntries;
static constexpr std::size_t _maxBadConsecutiveAttemptCount{ 5 };
static constexpr std::chrono::seconds _throttlingDuration{ 3 };
struct AttemptInfo
{
Wt::WDateTime nextAttempt;
std::size_t badConsecutiveAttemptCount{};
};
std::unordered_map<boost::asio::ip::address, AttemptInfo> _attemptsInfo;
};
} // namespace lms::auth
@@ -24,73 +24,72 @@
#include "internal/InternalPasswordService.hpp"
#ifdef LMS_SUPPORT_PAM
#include "pam/PAMPasswordService.hpp"
#include "pam/PAMPasswordService.hpp"
#endif // LMS_SUPPORT_PAM
#include "services/auth/Types.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "core/Exception.hpp"
#include "core/ILogger.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "services/auth/Types.hpp"
namespace lms::auth
{
static const Wt::Auth::SHA1HashFunction sha1Function;
static const Wt::Auth::SHA1HashFunction sha1Function;
std::unique_ptr<IPasswordService>
createPasswordService(std::string_view passwordAuthenticationBackend, db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
{
if (passwordAuthenticationBackend == "internal")
return std::make_unique<InternalPasswordService>(db, maxThrottlerEntries, authTokenService);
std::unique_ptr<IPasswordService>
createPasswordService(std::string_view passwordAuthenticationBackend, db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
{
if (passwordAuthenticationBackend == "internal")
return std::make_unique<InternalPasswordService>(db, maxThrottlerEntries, authTokenService);
#ifdef LMS_SUPPORT_PAM
else if (passwordAuthenticationBackend == "pam")
return std::make_unique<PAMPasswordService>(db, maxThrottlerEntries, authTokenService);
else if (passwordAuthenticationBackend == "pam")
return std::make_unique<PAMPasswordService>(db, maxThrottlerEntries, authTokenService);
#endif // LMS_SUPPORT_PAM
throw Exception {"Authentication backend '" + std::string {passwordAuthenticationBackend} + "' is not supported!"};
}
throw Exception{ "Authentication backend '" + std::string{ passwordAuthenticationBackend } + "' is not supported!" };
}
PasswordServiceBase::PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
: AuthServiceBase {db}
, _loginThrottler {maxThrottlerEntries}
, _authTokenService {authTokenService}
{
}
PasswordServiceBase::PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
: AuthServiceBase{ db }
, _loginThrottler{ maxThrottlerEntries }
, _authTokenService{ authTokenService }
{
}
PasswordServiceBase::CheckResult
PasswordServiceBase::checkUserPassword(const boost::asio::ip::address& clientAddress, std::string_view loginName, std::string_view password)
{
LMS_LOG(AUTH, DEBUG, "Checking password for user '" << loginName << "'");
PasswordServiceBase::CheckResult
PasswordServiceBase::checkUserPassword(const boost::asio::ip::address& clientAddress, std::string_view loginName, std::string_view password)
{
LMS_LOG(AUTH, DEBUG, "Checking password for user '" << loginName << "'");
// Do not waste too much resource on brute force attacks (optim)
{
std::shared_lock lock {_mutex};
// Do not waste too much resource on brute force attacks (optim)
{
std::shared_lock lock{ _mutex };
if (_loginThrottler.isClientThrottled(clientAddress))
return {CheckResult::State::Throttled};
}
if (_loginThrottler.isClientThrottled(clientAddress))
return { CheckResult::State::Throttled };
}
const bool match {checkUserPassword(loginName, password)};
{
std::unique_lock lock {_mutex};
const bool match{ checkUserPassword(loginName, password) };
{
std::unique_lock lock{ _mutex };
if (_loginThrottler.isClientThrottled(clientAddress))
return {CheckResult::State::Throttled};
if (_loginThrottler.isClientThrottled(clientAddress))
return { CheckResult::State::Throttled };
if (match)
{
_loginThrottler.onGoodClientAttempt(clientAddress);
if (match)
{
_loginThrottler.onGoodClientAttempt(clientAddress);
const db::UserId userId {getOrCreateUser(loginName)};
onUserAuthenticated(userId);
return {CheckResult::State::Granted, userId};
}
else
{
_loginThrottler.onBadClientAttempt(clientAddress);
return {CheckResult::State::Denied};
}
}
}
const db::UserId userId{ getOrCreateUser(loginName) };
onUserAuthenticated(userId);
return { CheckResult::State::Granted, userId };
}
else
{
_loginThrottler.onBadClientAttempt(clientAddress);
return { CheckResult::State::Denied };
}
}
}
} // namespace lms::auth
@@ -21,40 +21,40 @@
#include <shared_mutex>
#include "services/auth/IPasswordService.hpp"
#include "AuthServiceBase.hpp"
#include "LoginThrottler.hpp"
#include "services/auth/IPasswordService.hpp"
namespace lms::db
{
class Db;
class Session;
}
class Db;
class Session;
} // namespace lms::db
namespace lms::auth
{
class PasswordServiceBase : public IPasswordService, public AuthServiceBase
{
public:
PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
class PasswordServiceBase : public IPasswordService, public AuthServiceBase
{
public:
PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
PasswordServiceBase(const PasswordServiceBase&) = delete;
PasswordServiceBase& operator=(const PasswordServiceBase&) = delete;
PasswordServiceBase(PasswordServiceBase&&) = delete;
PasswordServiceBase& operator=(PasswordServiceBase&&) = delete;
PasswordServiceBase(const PasswordServiceBase&) = delete;
PasswordServiceBase& operator=(const PasswordServiceBase&) = delete;
PasswordServiceBase(PasswordServiceBase&&) = delete;
PasswordServiceBase& operator=(PasswordServiceBase&&) = delete;
protected:
IAuthTokenService& getAuthTokenService() { return _authTokenService; }
protected:
IAuthTokenService& getAuthTokenService() { return _authTokenService; }
private:
virtual bool checkUserPassword(std::string_view loginName, std::string_view password) = 0;
private:
virtual bool checkUserPassword(std::string_view loginName, std::string_view password) = 0;
CheckResult checkUserPassword(const boost::asio::ip::address& clientAddress,
std::string_view loginName,
std::string_view password) override;
CheckResult checkUserPassword(const boost::asio::ip::address& clientAddress,
std::string_view loginName,
std::string_view password) override;
std::shared_mutex _mutex;
LoginThrottler _loginThrottler;
IAuthTokenService& _authTokenService;
};
}
std::shared_mutex _mutex;
LoginThrottler _loginThrottler;
IAuthTokenService& _authTokenService;
};
} // namespace lms::auth
@@ -20,21 +20,21 @@
#pragma once
#include "services/auth/IEnvService.hpp"
#include "AuthServiceBase.hpp"
namespace lms::auth
{
class HttpHeadersEnvService : public IEnvService, public AuthServiceBase
{
public:
HttpHeadersEnvService(db::Db& db);
class HttpHeadersEnvService : public IEnvService, public AuthServiceBase
{
public:
HttpHeadersEnvService(db::Db& db);
private:
CheckResult processEnv(const Wt::WEnvironment& env) override;
CheckResult processRequest(const Wt::Http::Request& request) override;
private:
CheckResult processEnv(const Wt::WEnvironment& env) override;
CheckResult processRequest(const Wt::Http::Request& request) override;
std::string _fieldName;
};
std::string _fieldName;
};
} // namespace lms::auth
@@ -18,14 +18,15 @@
*/
#include "InternalPasswordService.hpp"
#include <Wt/WRandom.h>
#include "services/auth/IAuthTokenService.hpp"
#include "services/auth/Types.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "core/Exception.hpp"
#include "core/ILogger.hpp"
#include "database/Session.hpp"
#include "database/User.hpp"
#include "services/auth/IAuthTokenService.hpp"
#include "services/auth/Types.hpp"
namespace lms::auth
{
@@ -120,14 +121,13 @@ namespace lms::auth
{
const std::string salt{ Wt::WRandom::generateId(32) };
return { salt, _hashFunc.compute(std::string {password}, salt) };
return { salt, _hashFunc.compute(std::string{ password }, salt) };
}
void
InternalPasswordService::hashRandomPassword() const
InternalPasswordService::hashRandomPassword() const
{
hashPassword(Wt::WRandom::generateId(32));
}
} // namespace lms::auth
@@ -23,8 +23,9 @@
#include <Wt/Auth/PasswordStrengthValidator.h>
#include "database/User.hpp"
#include "PasswordServiceBase.hpp"
#include "LoginThrottler.hpp"
#include "PasswordServiceBase.hpp"
namespace lms::auth
{
@@ -36,17 +37,17 @@ namespace lms::auth
InternalPasswordService(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
private:
bool checkUserPassword(std::string_view loginName, std::string_view password) override;
bool checkUserPassword(std::string_view loginName, std::string_view password) override;
bool canSetPasswords() const override;
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
void setPassword(db::UserId userId, std::string_view newPassword) override;
bool canSetPasswords() const override;
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
void setPassword(db::UserId userId, std::string_view newPassword) override;
db::User::PasswordHash hashPassword(std::string_view password) const;
void hashRandomPassword() const;
db::User::PasswordHash hashPassword(std::string_view password) const;
void hashRandomPassword() const;
const Wt::Auth::BCryptHashFunction _hashFunc{ 7 }; // TODO parametrize this
Wt::Auth::PasswordStrengthValidator _validator;
const Wt::Auth::BCryptHashFunction _hashFunc{ 7 }; // TODO parametrize this
Wt::Auth::PasswordStrengthValidator _validator;
};
}
} // namespace lms::auth
@@ -20,15 +20,15 @@
#include "PAMPasswordService.hpp"
#ifndef LMS_SUPPORT_PAM
#error "Should not compile this"
#error "Should not compile this"
#endif
#include <cstring>
#include <security/pam_appl.h>
#include "services/auth/Types.hpp"
#include "database/Session.hpp"
#include "core/ILogger.hpp"
#include "database/Session.hpp"
#include "services/auth/Types.hpp"
namespace lms::auth
{
@@ -53,7 +53,7 @@ namespace lms::auth
public:
PAMContext(std::string_view loginName)
{
int err{ pam_start("lms", std::string {loginName}.c_str(), &_conv, &_pamh) };
int err{ pam_start("lms", std::string{ loginName }.c_str(), &_conv, &_pamh) };
if (err != PAM_SUCCESS)
throw PAMError{ "start failed", _pamh, err };
}
@@ -92,7 +92,8 @@ namespace lms::auth
class AuthenticateConvContext final : public ConvContext
{
public:
AuthenticateConvContext(std::string_view password) : _password{ password } {}
AuthenticateConvContext(std::string_view password)
: _password{ password } {}
std::string_view getPassword() const { return _password; }
@@ -160,7 +161,7 @@ namespace lms::auth
pam_conv _conv{ &PAMContext::conv, this };
pam_handle_t* _pamh{};
};
}
} // namespace
bool PAMPasswordService::checkUserPassword(std::string_view loginName, std::string_view password)
{
@@ -197,4 +198,3 @@ namespace lms::auth
}
} // namespace lms::auth
@@ -25,15 +25,15 @@
namespace lms::auth
{
class PAMPasswordService: public PasswordServiceBase
{
public:
using PasswordServiceBase::PasswordServiceBase;
class PAMPasswordService : public PasswordServiceBase
{
public:
using PasswordServiceBase::PasswordServiceBase;
private:
bool checkUserPassword(std::string_view loginName,std::string_view password) override;
bool canSetPasswords() const override;
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
void setPassword(db::UserId userId, std::string_view newPassword) override;
};
}
private:
bool checkUserPassword(std::string_view loginName, std::string_view password) override;
bool canSetPasswords() const override;
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
void setPassword(db::UserId userId, std::string_view newPassword) override;
};
} // namespace lms::auth
@@ -17,58 +17,56 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
/* This file contains some classes in order to get info from file using the libavconv */
#pragma once
#include <Wt/WDateTime.h>
#include <boost/asio/ip/address.hpp>
#include <optional>
#include <string>
#include <string_view>
#include <boost/asio/ip/address.hpp>
#include <Wt/WDateTime.h>
#include "database/UserId.hpp"
namespace lms::db
{
class Db;
class User;
}
class Db;
class User;
} // namespace lms::db
namespace lms::auth
{
class IAuthTokenService
{
public:
virtual ~IAuthTokenService() = default;
class IAuthTokenService
{
public:
virtual ~IAuthTokenService() = default;
// Auth Token services
struct AuthTokenProcessResult
{
enum class State
{
Granted,
Throttled,
Denied,
};
// Auth Token services
struct AuthTokenProcessResult
{
enum class State
{
Granted,
Throttled,
Denied,
};
struct AuthTokenInfo
{
db::UserId userId;
Wt::WDateTime expiry;
};
struct AuthTokenInfo
{
db::UserId userId;
Wt::WDateTime expiry;
};
State state {State::Denied};
std::optional<AuthTokenInfo> authTokenInfo {};
};
State state{ State::Denied };
std::optional<AuthTokenInfo> authTokenInfo{};
};
// Provided token is only accepted once
virtual AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) = 0;
// Provided token is only accepted once
virtual AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) = 0;
// Returns a one time token
virtual std::string createAuthToken(db::UserId userid, const Wt::WDateTime& expiry) = 0;
virtual void clearAuthTokens(db::UserId userid) = 0;
};
// Returns a one time token
virtual std::string createAuthToken(db::UserId userid, const Wt::WDateTime& expiry) = 0;
virtual void clearAuthTokens(db::UserId userid) = 0;
};
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntryCount);
}
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntryCount);
} // namespace lms::auth
@@ -26,44 +26,44 @@
namespace lms::db
{
class Db;
class Session;
}
class Db;
class Session;
} // namespace lms::db
namespace Wt
{
class WEnvironment;
class WEnvironment;
}
namespace Wt::Http
{
class Request;
class Request;
}
namespace lms::auth
{
class IEnvService
{
public:
virtual ~IEnvService() = default;
class IEnvService
{
public:
virtual ~IEnvService() = default;
// Auth Token services
struct CheckResult
{
enum class State
{
Granted,
Denied,
Throttled,
};
// Auth Token services
struct CheckResult
{
enum class State
{
Granted,
Denied,
Throttled,
};
State state {State::Denied};
std::optional<db::UserId> userId {};
};
State state{ State::Denied };
std::optional<db::UserId> userId{};
};
virtual CheckResult processEnv(const Wt::WEnvironment& env) = 0;
virtual CheckResult processRequest(const Wt::Http::Request& request) = 0;
};
virtual CheckResult processEnv(const Wt::WEnvironment& env) = 0;
virtual CheckResult processRequest(const Wt::Http::Request& request) = 0;
};
std::unique_ptr<IEnvService> createEnvService(std::string_view backendName, db::Db& db);
std::unique_ptr<IEnvService> createEnvService(std::string_view backendName, db::Db& db);
} // namespace lms::auth
@@ -19,59 +19,59 @@
#pragma once
#include <string_view>
#include <optional>
#include <string_view>
#include <boost/asio/ip/address.hpp>
#include <Wt/WDateTime.h>
#include <Wt/Dbo/ptr.h>
#include <Wt/WDateTime.h>
#include <boost/asio/ip/address.hpp>
#include "services/auth/Types.hpp"
#include "database/UserId.hpp"
#include "services/auth/Types.hpp"
namespace lms::db
{
class Db;
class User;
}
class Db;
class User;
} // namespace lms::db
namespace lms::auth
{
class IAuthTokenService;
class IAuthTokenService;
class IPasswordService
{
public:
virtual ~IPasswordService() = default;
class IPasswordService
{
public:
virtual ~IPasswordService() = default;
struct CheckResult
{
enum class State
{
Granted,
Denied,
Throttled,
};
State state {State::Denied};
std::optional<db::UserId> userId {};
std::optional<Wt::WDateTime> expiry {};
};
virtual CheckResult checkUserPassword(const boost::asio::ip::address& clientAddress,
std::string_view loginName,
std::string_view password) = 0;
struct CheckResult
{
enum class State
{
Granted,
Denied,
Throttled,
};
State state{ State::Denied };
std::optional<db::UserId> userId{};
std::optional<Wt::WDateTime> expiry{};
};
virtual CheckResult checkUserPassword(const boost::asio::ip::address& clientAddress,
std::string_view loginName,
std::string_view password)
= 0;
virtual bool canSetPasswords() const = 0;
virtual bool canSetPasswords() const = 0;
enum class PasswordAcceptabilityResult
{
OK,
TooWeak,
MustMatchLoginName,
};
virtual PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view password, const PasswordValidationContext& context) const = 0;
virtual void setPassword(db::UserId userId, std::string_view newPassword) = 0;
};
std::unique_ptr<IPasswordService> createPasswordService(std::string_view authPasswordBackend, db::Db& db, std::size_t maxThrottlerEntryCount, IAuthTokenService& authTokenService);
}
enum class PasswordAcceptabilityResult
{
OK,
TooWeak,
MustMatchLoginName,
};
virtual PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view password, const PasswordValidationContext& context) const = 0;
virtual void setPassword(db::UserId userId, std::string_view newPassword) = 0;
};
std::unique_ptr<IPasswordService> createPasswordService(std::string_view authPasswordBackend, db::Db& db, std::size_t maxThrottlerEntryCount, IAuthTokenService& authTokenService);
} // namespace lms::auth
@@ -20,50 +20,54 @@
#pragma once
#include <string>
#include "database/Types.hpp"
#include "core/Exception.hpp"
#include "database/Types.hpp"
namespace lms::auth
{
class Exception : public core::LmsException
{
using core::LmsException::LmsException;
};
class Exception : public core::LmsException
{
using core::LmsException::LmsException;
};
class NotImplementedException : public Exception
{
public:
NotImplementedException() : Exception {"Not implemented"} {}
};
class NotImplementedException : public Exception
{
public:
NotImplementedException()
: Exception{ "Not implemented" } {}
};
class UserNotFoundException : public Exception
{
public:
UserNotFoundException() : Exception {"User not found"} {}
};
class UserNotFoundException : public Exception
{
public:
UserNotFoundException()
: Exception{ "User not found" } {}
};
struct PasswordValidationContext
{
std::string loginName;
db::UserType userType;
};
struct PasswordValidationContext
{
std::string loginName;
db::UserType userType;
};
class PasswordException : public Exception
{
public:
using Exception::Exception;
};
class PasswordException : public Exception
{
public:
using Exception::Exception;
};
class PasswordTooWeakException : public PasswordException
{
public:
PasswordTooWeakException() : PasswordException {"Password too weak"} {}
};
class PasswordMustMatchLoginNameException : public PasswordException
{
public:
PasswordMustMatchLoginNameException() : PasswordException {"Password must match login name"} {}
};
}
class PasswordTooWeakException : public PasswordException
{
public:
PasswordTooWeakException()
: PasswordException{ "Password too weak" } {}
};
class PasswordMustMatchLoginNameException : public PasswordException
{
public:
PasswordMustMatchLoginNameException()
: PasswordException{ "Password must match login name" } {}
};
} // namespace lms::auth