* Prevent printing in noninteractive mode * Allow PAM modules to be configurated directly in pam.d * Configuration should be redable by everybody * Add a way to read ip address in when no IP is awailable * Enable read ip from pam * Fix veritas BUG
97 lines
2.8 KiB
C++
97 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include "rublon/utils.hpp"
|
|
#include <memory_resource>
|
|
#include <rublon/error.hpp>
|
|
#include <rublon/memory.hpp>
|
|
|
|
#include <string>
|
|
#include <tl/expected.hpp>
|
|
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <unistd.h>
|
|
#include <utility>
|
|
|
|
namespace rublon {
|
|
|
|
using socket_t = int;
|
|
constexpr socket_t invalid_socket = -1;
|
|
|
|
class unique_fd {
|
|
socket_t fd_ = invalid_socket;
|
|
|
|
public:
|
|
unique_fd() = default;
|
|
explicit unique_fd(socket_t fd) : fd_(fd) {}
|
|
|
|
~unique_fd() {
|
|
close(fd_);
|
|
}
|
|
|
|
unique_fd(const unique_fd &) = delete;
|
|
unique_fd & operator=(const unique_fd &) = delete;
|
|
|
|
unique_fd(unique_fd && other) noexcept : fd_(std::exchange(other.fd_, invalid_socket)) {}
|
|
unique_fd & operator=(unique_fd && other) noexcept {
|
|
if(this != &other) {
|
|
close(fd_);
|
|
fd_ = std::exchange(other.fd_, invalid_socket);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
socket_t get() const noexcept {
|
|
return fd_;
|
|
}
|
|
socket_t release() noexcept {
|
|
return std::exchange(fd_, invalid_socket);
|
|
}
|
|
void reset(socket_t fd = invalid_socket) noexcept {
|
|
if(fd_ != fd) {
|
|
close(fd_);
|
|
fd_ = fd;
|
|
}
|
|
}
|
|
|
|
explicit operator bool() const noexcept {
|
|
return fd_ != invalid_socket;
|
|
}
|
|
};
|
|
|
|
// this function is a little hack just to fix RSUP-1413
|
|
// When loging to rublon from withing the host itself, there is no IP delivered through any 'pam_item'
|
|
// but we need to log from what place the request did came.
|
|
tl::expected< std::pmr::string, Error > getDefaultRouteIp(std::pmr::memory_resource * mr) {
|
|
log(LogLevel::Debug, "Reading default route IP");
|
|
unique_fd sock(::socket(AF_INET, SOCK_DGRAM, 0));
|
|
if(!sock){
|
|
log(LogLevel::Warning, "Cant create socket");
|
|
return tl::unexpected{Error{RublonRuntimeException::CantCreateSocket}};
|
|
}
|
|
|
|
sockaddr_in remote{};
|
|
remote.sin_family = AF_INET;
|
|
remote.sin_port = htons(53);
|
|
::inet_pton(AF_INET, "8.8.8.8", &remote.sin_addr);
|
|
|
|
// we use UDP so no actual connection is estamblished. Only trying to get an interface
|
|
if(::connect(sock.get(), ( struct sockaddr * ) &remote, sizeof(remote)) < 0) {
|
|
log(LogLevel::Warning, "Cant connect to socket");
|
|
return tl::unexpected{Error{RublonRuntimeException::ConnectionFailed}};
|
|
}
|
|
|
|
sockaddr_in local{};
|
|
socklen_t len = sizeof(local);
|
|
if(::getsockname(sock.get(), ( struct sockaddr * ) &local, &len) < 0) {
|
|
log(LogLevel::Warning, "Cant get socket name");
|
|
return tl::unexpected{Error{RublonRuntimeException::CantGetSocketName}};
|
|
}
|
|
|
|
char ip[INET_ADDRSTRLEN];
|
|
::inet_ntop(AF_INET, &local.sin_addr, ip, sizeof(ip));
|
|
return std::pmr::string{ip, mr};
|
|
}
|
|
} // namespace rublon
|