#include #include #include #include #include #include #include #include #include #include #define DLL_PUBLIC __attribute__((visibility("default"))) using namespace std; 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; LinuxPam pam{pamh}; auto rublonConfig = ConfigurationFactory{}.systemConfig(); if(not rublonConfig.has_value()) { pam.print("Rublon configuration not exists"); pam.print("Please create /etc/rublon.config file"); return PAM_SUCCESS; } std::byte sharedMemory[32 * 1024] = {}; std::pmr::monotonic_buffer_resource mr{sharedMemory, std::size(sharedMemory)}; std::pmr::unsynchronized_pool_resource rublonPoolResource{&mr}; std::pmr::set_default_resource(&rublonPoolResource); CoreHandler CH{rublonConfig.value()}; auto selectMethod = [&](const MethodSelect & selector) { return selector.create(pam); }; auto confirmMethod = [&](const PostMethod & confirm) { return confirm.fire(CH); }; auto confirmCode = [&](const MethodProxy & method) { return method.fire(CH, pam); }; auto allowLogin = [&](const AuthenticationStatus & status) -> tl::expected< int, Error > { if(status.userAuthorized()) { rublon::log(rublon::LogLevel::Info, "Auth OK"); pam.print("RUBLON authentication SUCCESS!\n"); return PAM_SUCCESS; } else { rublon::log(rublon::LogLevel::Info, "User unauthorized"); pam.print("RUBLON authentication FAILED"); return PAM_MAXTRIES; } }; auto mapError = [&](const Error & error) -> tl::expected< int, Error > { rublon::log( LogLevel::Error, "auth problems due to %d class and %d category", error.errorClass(), static_cast< int >(error.category())); if(error.is< PamBaypass >()) { pam.print("\n RUBLON authentication bypased"); return PAM_SUCCESS; } pam.print("RUBLON authentication FAILED"); rublon::log(LogLevel::Warning, "User login failed"); return PAM_MAXTRIES; }; auto ret = Init{rublonConfig.value()} .fire(CH, pam) // .and_then(selectMethod) .and_then(confirmMethod) .and_then(confirmCode) .and_then(allowLogin) .or_else(mapError); return ret.value_or(PAM_MAXTRIES); }