#include #include #include #include #include #include #include #include #include #include #include #include #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; }; Session session{pam}; auto ok = rublon::RublonFactory{}.initializeSession(session); if(not ok.has_value()) { return printAuthMessageAndExit(AuthenticationStatus::Action::Bypass); } if(!session.config().logging) { g_level = LogLevel::Warning; } CoreHandler_t CH{session.config()}; 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, CH, pam); }; auto finalizeTransaction = [&](const AuthenticationStatus & status) mutable -> tl::expected< AuthenticationStatus, Error > { if(status.userAuthorized()) { Finish{session, status.accessToken()}.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{session}; const auto ret = ca.call(CH, session.config().systemToken).or_else(mapError); if(not ret.has_value()) { log(LogLevel::Error, "Check Application step failed, check configration"); return PAM_MAXTRIES; } } auto ret = Init{session} .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); }