#pragma once #include #include #include #include namespace rublon { class LinuxPam { pam_handle_t * pamh; bool _noninteractive{false}; public: LinuxPam(pam_handle_t * handler) : pamh{handler} {} void enableNoninteractive(){ _noninteractive = true; } rublon::NonOwningPtr< const char > ip() const { const void * ip = NULL; pam_get_item(pamh, PAM_RHOST, &ip); if(ip == NULL) { rublon::log(rublon::LogLevel::Warning, "Cant read ip from linux PAM"); ip = ""; } return ( const char * ) ip; } rublon::NonOwningPtr< const char > username() const { const char * user = NULL; pam_get_user(pamh, &user, nullptr); if(user == NULL) { rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM"); user = ""; } return user; } template < typename... Ti > void print(const char * fmt, Ti... ti) const noexcept { if(_noninteractive){ log(LogLevel::Info, "pam_print ommited due working in noninteractive mode"); return; } char buf[256] = {}; sprintf(buf, fmt, std::forward< Ti >(ti)...); if(auto r = pam_prompt(pamh, PAM_TEXT_INFO, nullptr, fmt, std::forward< Ti >(ti)...); r != PAM_SUCCESS) { log(LogLevel::Error, "pam_print returned with error code %d", r); } } template < typename Fun, typename... Ti > auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept { assert(_noninteractive == false); char * response = nullptr; pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &response, fmt, std::forward< Ti >(ti)...); if(response) { auto ret = f(response); free(response); return ret; } return std::result_of_t< Fun(char *) >(); } }; } // namespace rublon