Provide better LOG function, refactor cmake

This commit is contained in:
Bartosz Wieczorek 2023-07-21 13:23:27 +02:00
parent 5ad212cd62
commit 3cb8567f42
9 changed files with 110 additions and 78 deletions

View File

@ -8,11 +8,11 @@ add_library(rublon-ssh
include/rublon/curl.hpp
include/rublon/span.hpp
include/rublon/sign.hpp
include/rublon/utils.hpp
include/rublon/CoreHandler.hpp
include/rublon/configuration.hpp
)
#set(CMAKE_SHARED_LINKER_FLAGS "-fpic -static-libstdc++ -fvisibility=hidden -ffunction-sections -fdata-sections -fwhole-program")
target_include_directories(rublon-ssh
PUBLIC INTERFACE

View File

@ -27,7 +27,7 @@ template < typename Impl >
class CoreHandlerInterface {
public:
tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const {
rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__);
rublon::log(LogLevel::Debug, "%s", __PRETTY_FUNCTION__);
return static_cast< const Impl * >(this)->request(path, body);
}
};
@ -42,12 +42,10 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
}
void signRequest(std::pmr::monotonic_buffer_resource & mr, Request & request) const {
rublon::debugLog("[TMP]",__PRETTY_FUNCTION__);
request.headers["X-Rublon-Signature"] = xRublonSignature(mr, request.body);
}
bool responseSigned(const Response & response) const {
rublon::debugLog("[TMP]",__PRETTY_FUNCTION__);
const auto & xRubResp = response.headers.at("x-rublon-signature");
const auto & sign = signData(response.body, secretKey);
return xRubResp == sign.data();
@ -62,7 +60,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
CoreHandler(const rublon::Configuration & config) : secretKey{config.parameters.secretKey}, url{config.parameters.apiServer} {}
tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const {
rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__);
rublon::log(LogLevel::Info, "Sending request to %s", path.data());
std::byte _buffer[16 * 1024];
std::pmr::monotonic_buffer_resource mr{_buffer, sizeof(_buffer)};
@ -79,32 +77,30 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
request.body = jsonStr.GetString();
rublon::debugLog("[TMP] request", "sign");
signRequest(mr, request);
// std::pmr::string uri{url + path.data(), &mr};
std::pmr::string uri{url + path.data(), &mr};
// rublon::debugLog("[TMP] send", request.body.c_str());
// auto response = http.request(uri, request);
auto response = http.request(uri, request);
// if(not response.has_value()) {
if(not response.has_value()) {
return tl::unexpected{CoreHandlerError::ConnectionError};
// }
// if(not responseSigned(*response)) {
// return tl::unexpected{CoreHandlerError::BadSigature};
// }
}
if(not responseSigned(*response)) {
return tl::unexpected{CoreHandlerError::BadSigature};
}
// rublon::Document resp{&alloc};
// resp.Parse(response->body.c_str());
rublon::Document resp{&alloc};
resp.Parse(response->body.c_str());
// if(resp.HasParseError() or not resp.HasMember("result")) {
// return tl::unexpected{CoreHandlerError::BrokenData};
// }
// if(resp["result"].HasMember("exception")) {
// return tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException, resp["result"]["exception"].GetString()}};
// }
if(resp.HasParseError() or not resp.HasMember("result")) {
return tl::unexpected{CoreHandlerError::BrokenData};
}
if(resp["result"].HasMember("exception")) {
return tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException, resp["result"]["exception"].GetString()}};
}
// return resp;
return resp;
}
};

View File

@ -15,41 +15,37 @@
namespace rublon {
static size_t WriteMemoryCallback(void * contents, size_t size, size_t nmemb, void * userp) {
size_t realsize = size * nmemb;
size_t realsize = size * nmemb;
reinterpret_cast< std::string * >(userp)->append(static_cast< const char * >(contents), realsize);
return realsize;
}
struct Request{
std::map<std::string, std::string> headers;
struct Request {
std::map< std::string, std::string > headers;
std::string body;
};
struct Response{
std::map<std::string, std::string> headers;
struct Response {
std::map< std::string, std::string > headers;
std::string body;
};
class CURL {
std::unique_ptr< ::CURL, void (*)(::CURL *) > curl;
public:
CURL() : curl{std::unique_ptr< ::CURL, void (*)(::CURL *) >(curl_easy_init(), curl_easy_cleanup)} {}
std::optional< Response > request(std::string_view uri, const Request &request) const {
rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__);
std::optional< Response > request(std::string_view uri, const Request & request) const {
std::string response_data;
response_data.reserve(1000);
Response response;
/// TODO this can be done on stack using pmr
auto curl_headers = std::unique_ptr< curl_slist, void (*)(curl_slist *) >(nullptr, curl_slist_free_all);
std::for_each(request.headers.begin(), request.headers.end(), [&](auto header) {
curl_headers.reset(curl_slist_append(curl_headers.release(),(header.first + ": " + header.second).c_str()));
curl_headers.reset(curl_slist_append(curl_headers.release(), (header.first + ": " + header.second).c_str()));
});
curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1);
@ -61,21 +57,20 @@ class CURL {
curl_easy_setopt(curl.get(), CURLOPT_HEADER, 1);
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_data);
rublon::debugLog("[TMP] calling curl",__PRETTY_FUNCTION__);
rublon::log(LogLevel::Debug, "Request send uri:{%s} body:{%s}", uri.data(), request.body.c_str());
auto res = curl_easy_perform(curl.get());
if(res != CURLE_OK) {
// debugLog("No response from Rublon server (perform)", "");
return std::nullopt;
}
long size;
curl_easy_getinfo(curl.get(), CURLINFO_HEADER_SIZE, &size);
///TODO ogarnąć alokację pamięci
response.headers = details::headers({response_data.data(), static_cast<std::size_t>(size)});
response.body = response_data.substr(size);
/// TODO ogarnąć alokację pamięci
response.headers = details::headers({response_data.data(), static_cast< std::size_t >(size)});
response.body = response_data.substr(size);
return response;
}

View File

@ -35,7 +35,6 @@ class MethodFactory {
template < typename Array_t >
tl::expected< Method, PamAction > create(const Array_t & methods) const {
rublon::debugLog("[TMP] ",__PRETTY_FUNCTION__);
std::pmr::map< int, std::pmr::string > methods_id;
pam.print("%s", "");
int i;

View File

@ -23,22 +23,24 @@ class LinuxPam {
public:
LinuxPam(pam_handle_t * handler) : pamh{handler} {}
rublon::NonOwningPtr< const char > ip() const {
const void * ip = NULL;
pam_get_item(pamh, PAM_RHOST, &ip);
if(ip == NULL)
if(ip == NULL) {
rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM");
ip = "";
rublon::debugLog(__PRETTY_FUNCTION__, (const char*)ip);
return (const char*)ip;
}
return ( const char * ) ip;
}
rublon::NonOwningPtr< const char > username() const {
const char * user = NULL;
pam_get_user(pamh, &user, nullptr);
if(user == NULL)
if(user == NULL) {
rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM");
user = "";
rublon::debugLog(__PRETTY_FUNCTION__, user);
}
return user;
}
@ -50,7 +52,7 @@ class LinuxPam {
template < typename Fun, typename... Ti >
[[nodiscard]] auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept {
char * responseBuffer = nullptr;
pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &responseBuffer, fmt, std::forward< Ti... >(ti...));
pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &responseBuffer, fmt, std::forward< Ti... >(ti...));
if(responseBuffer) {
auto ret = f(responseBuffer);
free(responseBuffer);

View File

@ -62,13 +62,11 @@ class Init : public AuthenticationStep< Init< MethodFactory_t, PamInfo_t > > {
Init(pam_handle_t * pamHandler, const rublon::Configuration & config)
: _systemToken{config.parameters.systemToken}, _pamInfo{pamHandler}, _methodFactory{_pamInfo} {
rublon::debugLog("[TMP] Init ctor",__PRETTY_FUNCTION__);
}
/// TODO add core handler interface
template < typename Hander_t >
tl::expected< Method, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const {
rublon::debugLog("[TMP] init handle",__PRETTY_FUNCTION__);
char _buffer[1024];
std::pmr::monotonic_buffer_resource mr{_buffer, 1024};
@ -85,7 +83,7 @@ class Init : public AuthenticationStep< Init< MethodFactory_t, PamInfo_t > > {
params.AddMember("os", "Ubuntu 23.04", alloc); /// TODO add version to cmake
body.AddMember("params", std::move(params), alloc);
rublon::debugLog("[TMP] calling coreHandler",__PRETTY_FUNCTION__);
auto httpResponse = coreHandler.request(apiPath, body);
// if(httpResponse.has_value()) {

View File

@ -1,9 +1,11 @@
#pragma once
#include <algorithm>
#include <array>
#include <cctype>
#include <cstring>
#include <map>
#include <memory>
#include <memory_resource>
#include <sstream>
#include <string_view>
@ -16,19 +18,49 @@
#include <syslog.h>
namespace rublon {
enum LogLevel { Debug, Info, Warning, Error };
inline void debugLog(const char * message1, const char * message2) {
auto file_name = "/tmp/rublon.log";
auto fp = fopen(file_name, "a");
fprintf(fp, "[%s] %s %s\n", "cmake version", message1, message2);
fflush(fp);
fclose(fp);
// openlog("pam_rublon", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
// syslog(LOG_NOTICE, "[%s] %s %s", "cmake version", message1, message2);
// closelog();
namespace {
inline auto dateStr() {
std::array< char, 32 > date;
time_t now;
time(&now);
strftime(date.data(), date.size(), "%FT%TZ", gmtime(&now));
return date;
}
const auto LogLevelNames = {"Debug", "Info", "Warning", "Error"};
template < typename... Ti >
void log(LogLevel level, const char * fmt, Ti &&... ti) noexcept {
constexpr auto file_name = "/var/log/rublon-ssh.log";
if(level < 0)
return;
auto fp = std::unique_ptr< FILE, int (*)(FILE *) >(fopen(file_name, "a"), fclose);
if(fp) {
std::array< char, 1000 > line;
sprintf(line.data(), fmt, std::forward< Ti >(ti)...);
fprintf(fp.get(), "[%s] %s %s\n", "rublon_ssh_pam", dateStr().data(), line.data());
}
}
}
// inline void debugLog(const char * message1, const char * message2) {
// auto file_name = "/tmp/rublon.log";
// auto fp = fopen(file_name, "a");
// fprintf(fp, "[%s] %s %s\n", "cmake version", message1, message2);
// fflush(fp);
// fclose(fp);
//// openlog("pam_rublon", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
//// syslog(LOG_NOTICE, "[%s] %s %s", "cmake version", message1, message2);
//// closelog();
//}
template < typename T >
class NonOwningPtr {
T * object;

View File

@ -3,12 +3,29 @@ add_library(rublon-ssh-pam
pam.cpp
)
target_compile_options(rublon-ssh-pam
PUBLIC
-fno-exceptions
-fno-rtti
-fvisibility=hidden
-ffunction-sections
-fdata-sections
-fno-unwind-tables
-fno-asynchronous-unwind-tables
)
target_link_options(rublon-ssh-pam
PUBLIC
-fpic -shared
-fpic
-s
# -static-libstdc++
-Wl,--gc-sections
)
target_link_libraries(rublon-ssh-pam
PUBLIC
-lcurl -lssl -lcrypto rublon-ssh
rublon-ssh
-lcurl
-lssl
-lcrypto
)

View File

@ -9,6 +9,8 @@
#include <rublon/rublon.hpp>
#include <rublon/utils.hpp>
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
using namespace std;
namespace {
@ -22,30 +24,21 @@ Expected< rublon::Confirm > confirm() {}
} // namespace
PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__);
DLL_PUBLIC int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__);
DLL_PUBLIC int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__);
DLL_PUBLIC int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv) {
auto rublonConfig = rublon::ConfigurationFactory{}.systemConfig();
rublon::debugLog("[TMP]create core handler", "");
rublon::CoreHandler CH{rublonConfig.value()};
rublon::debugLog("[TMP]start", "");
auto action = rublon::Init{pamh, rublonConfig.value()}
.fire(CH) //
.and_then([](const auto & method) -> Expected< int > {
rublon::debugLog("[TMP]start", "init lambda");
return tl::unexpected{rublon::PamAction::accept};
});