* Remove dynamic memory usage from core * Refacor status check to use json pointers * Move access token to session * Remove code duplication * Fix compile warnings from rapidjson sources * Add 'interactive mode option to session configuration * Implement non interactive mode connector * Add 'non interactove' implementation * Apply rapidjson patch * Build on all cores * Rename build script * Split configure and build steps * Add scripts for building all images * Change bash to python for build scripts * Stop printing methods name in non interactive mode * Add trace log level, adn more params to init message * Fix build * Fix non interactive method selection and refactor vagrant files for debian like systems * Refactor log messages * Remove exces dependencies from vagrant configuration files * Fixed vagrantfiles * Added repo for rhel * Add nonInteractiveMode option * Added instalation script for pubkey * Fixed pubkey install script and postrm for rhel
122 lines
4.1 KiB
C++
122 lines
4.1 KiB
C++
#include <security/pam_appl.h>
|
|
#include <security/pam_client.h>
|
|
#include <security/pam_ext.h>
|
|
#include <security/pam_misc.h>
|
|
#include <security/pam_modules.h>
|
|
#include <syslog.h>
|
|
|
|
#include <rublon/check_application.hpp>
|
|
#include <rublon/error.hpp>
|
|
#include <rublon/error_handler.hpp>
|
|
#include <rublon/finish.hpp>
|
|
#include <rublon/rublon.hpp>
|
|
#include <rublon/utils.hpp>
|
|
|
|
#define DLL_PUBLIC __attribute__((visibility("default")))
|
|
|
|
DLL_PUBLIC int pam_sm_setcred([[maybe_unused]] pam_handle_t * pamh,
|
|
[[maybe_unused]] int flags,
|
|
[[maybe_unused]] int argc,
|
|
[[maybe_unused]] const char ** argv) {
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
DLL_PUBLIC int pam_sm_acct_mgmt([[maybe_unused]] pam_handle_t * pamh,
|
|
[[maybe_unused]] int flags,
|
|
[[maybe_unused]] int argc,
|
|
[[maybe_unused]] const char ** argv) {
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
DLL_PUBLIC int
|
|
pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unused]] int argc, [[maybe_unused]] const char ** argv) {
|
|
using namespace rublon;
|
|
details::initLog();
|
|
LinuxPam pam{pamh};
|
|
|
|
log(LogLevel::Info, "user '%s' authentication attempt", pam.username().get());
|
|
|
|
auto printAuthMessageAndExit = [&](const AuthenticationStatus status) {
|
|
switch(status.action()) {
|
|
case AuthenticationStatus::Action::Bypass:
|
|
log(LogLevel::Info, "user '%s' authentication BYPASSED", pam.username().get());
|
|
pam.print("RUBLON authentication BYPASSED");
|
|
return PAM_SUCCESS;
|
|
|
|
case AuthenticationStatus::Action::Denied:
|
|
log(LogLevel::Info, "user '%s' authentication FAILED", pam.username().get());
|
|
pam.print("RUBLON authentication FAILED");
|
|
return PAM_MAXTRIES;
|
|
|
|
case AuthenticationStatus::Action::Confirmed:
|
|
log(LogLevel::Info, "user '%s' authentication SUCCEEDED", pam.username().get());
|
|
pam.print("RUBLON authentication SUCCEEDED");
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
pam.print("RUBLON connector has exited with unknown code, access DENY!\n");
|
|
return PAM_MAXTRIES;
|
|
};
|
|
|
|
auto session = rublon::RublonFactory{}.startSession(pam);
|
|
if(not session.has_value()) {
|
|
return printAuthMessageAndExit(AuthenticationStatus::Action::Bypass);
|
|
}
|
|
|
|
if(!session->config().logging) {
|
|
g_level = LogLevel::Warning;
|
|
}
|
|
|
|
auto & CH = session.value().coreHandler();
|
|
|
|
auto selectMethod = [&](const MethodSelect & selector) { //
|
|
return selector.create(pam);
|
|
};
|
|
|
|
auto confirmMethod = [&](const PostMethod & postMethod) { //
|
|
return postMethod.handle(CH);
|
|
};
|
|
|
|
auto confirmCode = [&](const MethodProxy & method) mutable { //
|
|
return method.fire(session.value(), CH, pam);
|
|
};
|
|
|
|
auto finalizeTransaction = [&](const AuthenticationStatus & status) mutable -> tl::expected< AuthenticationStatus, Error > {
|
|
if(status.userAuthorized()) {
|
|
auto tok = std::string{status.accessToken().data()};
|
|
Finish finish{session.value(), std::move(tok)};
|
|
finish.handle(CH);
|
|
}
|
|
return status;
|
|
};
|
|
|
|
auto allowLogin = [&](const AuthenticationStatus & status) -> tl::expected< int, Error > { //
|
|
return printAuthMessageAndExit(status);
|
|
};
|
|
|
|
auto mapError = [&](const Error & error) -> tl::expected< int, Error > {
|
|
return printAuthMessageAndExit(rublon::ErrorHandler{pam, session->config()}.printErrorDetails(error));
|
|
};
|
|
|
|
{
|
|
CheckApplication ca;
|
|
const auto & config = session.value().config();
|
|
const auto ret = ca.call(CH, {config.systemToken.data(), config.systemToken.size()}).or_else(mapError);
|
|
if(not ret.has_value()) {
|
|
log(LogLevel::Error, "Check Application step failed, check configration");
|
|
return PAM_MAXTRIES;
|
|
}
|
|
}
|
|
|
|
auto ret = Init{session.value()}
|
|
.handle(CH, pam) //
|
|
.and_then(selectMethod)
|
|
.and_then(confirmMethod)
|
|
.and_then(confirmCode)
|
|
.and_then(finalizeTransaction)
|
|
.and_then(allowLogin)
|
|
.or_else(mapError);
|
|
|
|
return ret.value_or(PAM_MAXTRIES);
|
|
}
|