diff --git a/PAM/ssh/include/rublon/error_handler.hpp b/PAM/ssh/include/rublon/error_handler.hpp new file mode 100644 index 0000000..f63fd0a --- /dev/null +++ b/PAM/ssh/include/rublon/error_handler.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include "rublon/bits.hpp" +#include "rublon/configuration.hpp" +#include +#include +#include + +namespace rublon { +class ErrorHandler { + public: + const Pam_t & pam; + const Configuration & config; + AuthenticationStatus printErrorDetails(const Error & error) { + log(LogLevel::Error, "Process interrupted by {%s::%s}", error.errorClassName(), error.categoryName()); + if(error.is< RublonAuthenticationInterrupt >()) { + switch(error.get< RublonAuthenticationInterrupt >().errorClass) { + case RublonAuthenticationInterrupt::ErrorClass::UserBaypass: + return AuthenticationStatus::Action::Bypass; + case RublonAuthenticationInterrupt::ErrorClass::UserDenied: + pam.print("Access denied! Contact your administrator for more information"); + return AuthenticationStatus::Action::Denied; + case RublonAuthenticationInterrupt::ErrorClass::UserWaiting: + case RublonAuthenticationInterrupt::ErrorClass::UserPending: + pam.print( + "Your account is awaiting administrator's approval.\n" + "Contact your administrator and ask them to approve your account"); + return AuthenticationStatus::Action::Denied; + case RublonAuthenticationInterrupt::ErrorClass::UserNotFound: + return AuthenticationStatus::Action::Bypass; + } + } + + if(error.is< MethodError >()) { + switch(error.get< MethodError >().errorClass) { + case MethodError::ErrorClass::BadMethod: + return AuthenticationStatus::Action::Denied; + case MethodError::ErrorClass::BadUserInput: + return AuthenticationStatus::Action::Denied; + case MethodError::ErrorClass::NoMethodAvailable: + return AuthenticationStatus::Action::Denied; + } + } + + if(error.is< ConnectionError >()) { + if(config.failMode == FailMode::deny) { + pam.print("Incorrect response from the Rublon API, user bypassed"); + return AuthenticationStatus::Action::Bypass; + } else { + pam.print("Incorrect response from the Rublon API, user access denied"); + return AuthenticationStatus::Action::Denied; + } + } + + if(error.is< CoreHandlerError >()) { + const auto & reson = error.get< CoreHandlerError >().reson; + pam.print("Something went wrong and authentication could not be completed, contact your administrator"); + + ///TODO change to some kind of enum and remove string + if(reson == "UserBypassedException" or reson == "UserNotFoundException") + return AuthenticationStatus::Action::Bypass; + } + + if(error.is< WerificationError >()) { + switch(error.get< WerificationError >().errorClass) { + case WerificationError::ErrorClass::PasscodeException: + pam.print(R"(Incorrect passcode)"); + return AuthenticationStatus::Action::Denied; + case WerificationError::ErrorClass::BadInput: + pam.print(R"(Ensure that the Secret Key is correct.)"); + return AuthenticationStatus::Action::Denied; + } + } + + if(error.is< RublonCheckApplicationException >()) { + switch(error.get< RublonCheckApplicationException >().errorClass) { + case RublonCheckApplicationException::ErrorClass::ApplicationNotFoundException: + log(LogLevel::Error, R"(Could not find the application in the Rublon Admin Console.)"); + log(LogLevel::Error, R"(Ensure that the application exists and the SystemToken is correct.)"); + return AuthenticationStatus::Action::Denied; + case RublonCheckApplicationException::ErrorClass::InvalidSignatureException: + log(LogLevel::Error, R"(Could not verify the signature.)"); + log(LogLevel::Error, R"(Ensure that the Secret Key is correct.)"); + return AuthenticationStatus::Action::Denied; + case RublonCheckApplicationException::ErrorClass::UnsupportedVersionException: + log(LogLevel::Error, R"(The provided version of the app is unsupported.)"); + log(LogLevel::Error, R"(Try changing the app version.)"); + return AuthenticationStatus::Action::Denied; + } + } + + return AuthenticationStatus::Action::Denied; + } +}; +} // namespace rublon