#pragma once #ifdef __sun #include #include #include #include #include static int pam_vprompt_compat(pam_handle_t *pamh, int style, char **out, const char *fmt, va_list ap) { const struct pam_conv *conv = NULL; if (pam_get_item(pamh, PAM_CONV, (void **)&conv) != PAM_SUCCESS || !conv || !conv->conv) return PAM_SYSTEM_ERR; char buf[1024]; vsnprintf(buf, sizeof(buf), fmt, ap); struct pam_message msg = { .msg_style = style, .msg = buf }; struct pam_message *pmsg[1] = { &msg }; struct pam_response *resp = NULL; int r = conv->conv(1, pmsg, &resp, conv->appdata_ptr); if (r != PAM_SUCCESS) return r; if (out) { if (resp && resp[0].resp) *out = resp[0].resp; else *out = NULL; } if (resp) free(resp); // NIE zwalniaj *out; zwolni to wywołujący return PAM_SUCCESS; } static int pam_prompt_compat(pam_handle_t *pamh, int style, char **out, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int r = pam_vprompt_compat(pamh, style, out, fmt, ap); va_end(ap); return r; } #define pam_prompt pam_prompt_compat #else #include #include #endif #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 { #ifdef __sun void * ip = NULL; #else const void * ip = NULL; #endif pam_get_item(pamh, PAM_RHOST, &ip); if(ip == NULL) { rublon::log(rublon::LogLevel::Warning, "Cant read ip from linux PAM"); return ""; } return ( const char * ) ip; } rublon::NonOwningPtr< const char > username() const { #ifdef __sun char * user = NULL; #else const char * user = NULL; #endif pam_get_user(pamh, &user, nullptr); if(user == NULL) { rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM"); return ""; } 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