Bwi/ws based auth (#6)
* Add websocket implementation * Added configuration for build socket-io and rublon connector
This commit is contained in:
parent
25b29e6f32
commit
7715b6fb45
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(rublon-ssh LANGUAGES CXX)
|
||||
|
||||
include(CTest)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 0)
|
||||
set(PROJECT_VERSION_MINOR 1)
|
||||
@ -16,6 +17,21 @@ add_compile_options(-Wall -Wextra -Wpedantic -Wno-format-security)
|
||||
|
||||
option(ENABLE_TESTS "Enable tests" ON)
|
||||
|
||||
add_custom_target(CONFIG_IDE SOURCES ${CMAKE_CURRENT_LIST_DIR}/rsc/rublon.config.defaults)
|
||||
add_custom_target(INSTSCRIPTS_IDE SUORCES ${CMAKE_CURRENT_LIST_DIR}/service/postinst)
|
||||
|
||||
# TODO configure to fill sysconfdir in postinst
|
||||
# TODO add postrm that will disable PAM
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/rsc/rublon.config.defaults
|
||||
DESTINATION
|
||||
share/rublon
|
||||
COMPONENT
|
||||
PAM
|
||||
)
|
||||
|
||||
if (${ENABLE_TESTS})
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
@ -11,12 +11,14 @@ set(INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/method/OTP.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/method/SMS.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/method/passcode_based_auth.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/method/websocket_based_auth.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/non_owning_ptr.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/pam_action.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/pam.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/rublon.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/sign.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/utils.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/websockets.hpp
|
||||
)
|
||||
|
||||
add_library(rublon-ssh
|
||||
|
||||
@ -15,5 +15,7 @@ class CoreHandlerInterface {
|
||||
rublon::log(LogLevel::Debug, "%s", "CoreHandlerInterface::request");
|
||||
return static_cast< const Impl * >(this)->request(mr, path, body);
|
||||
}
|
||||
|
||||
// tl::expected< Document, Error >
|
||||
};
|
||||
} // namespace rublon
|
||||
|
||||
@ -18,8 +18,18 @@
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace rublon {
|
||||
|
||||
inline bool replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
size_t start_pos = str.find(from);
|
||||
if(start_pos == std::string::npos)
|
||||
return false;
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
size_t WriteMemoryCallback(void * contents, size_t size, size_t nmemb, void * userp) {
|
||||
const size_t realsize = size * nmemb;
|
||||
|
||||
@ -8,11 +8,47 @@
|
||||
#include <rublon/method/method_select.hpp>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace rublon {
|
||||
class Verify {};
|
||||
} // namespace rublon
|
||||
|
||||
namespace rublon {
|
||||
std::pmr::string osName(std::pmr::memory_resource *mr) {
|
||||
memory::MonotonicStackResource< 8 * 1024 > stackResource;
|
||||
using Params = Configuration::Parameters;
|
||||
Params configValues;
|
||||
|
||||
std::ifstream file(std::filesystem::path{"/etc/os-release"});
|
||||
if(not file.good())
|
||||
return {"unknown", mr};
|
||||
|
||||
std::pmr::string line{&stackResource};
|
||||
line.reserve(100);
|
||||
|
||||
while(std::getline(file, line)) {
|
||||
std::pmr::string _key{&stackResource};
|
||||
std::pmr::string _value{&stackResource};
|
||||
|
||||
if(!line.length())
|
||||
continue;
|
||||
|
||||
if(line[0] == '#' || line[0] == ';')
|
||||
continue;
|
||||
|
||||
auto posEqual = line.find('=');
|
||||
_key = line.substr(0, posEqual);
|
||||
_value = line.substr(posEqual + 1);
|
||||
|
||||
if(_key == "PRETTY_NAME"){
|
||||
return {_value, mr};
|
||||
}
|
||||
}
|
||||
|
||||
return {"unknown", mr};
|
||||
}
|
||||
|
||||
template < class MethodSelect_t = MethodSelect >
|
||||
class Init : public AuthenticationStep< Init< MethodSelect_t > > {
|
||||
using base_t = AuthenticationStep< Init< MethodSelect_t > >;
|
||||
@ -33,24 +69,23 @@ class Init : public AuthenticationStep< Init< MethodSelect_t > > {
|
||||
|
||||
template < typename PamInfo_t >
|
||||
void addParams(Document & coreRequest, const PamInfo_t & pam) const {
|
||||
memory::MonotonicStackResource< 256 > stackResource;
|
||||
std::pmr::string osname{&stackResource};
|
||||
memory::MonotonicStackResource< 512 > stackResource;
|
||||
std::pmr::string releaseInfo{&stackResource};
|
||||
auto & alloc = coreRequest.GetAllocator();
|
||||
|
||||
const auto hasIssueFile = readFile("/etc/issue", osname);
|
||||
const auto osnameTrimed = details::rtrim(hasIssueFile ? osname : "unknown");
|
||||
|
||||
if(not hasIssueFile) {
|
||||
const auto os= osName(&stackResource);
|
||||
|
||||
if(os== "unknown") {
|
||||
log(LogLevel::Warning, "No OS information available");
|
||||
}
|
||||
|
||||
Value os{osnameTrimed.data(), static_cast< unsigned >(osnameTrimed.size()), alloc};
|
||||
Value params{rapidjson::kObjectType};
|
||||
Value osNamePretty{os.data(), static_cast< unsigned >(os.size()), alloc};
|
||||
Value ip{pam.ip().get(), alloc};
|
||||
|
||||
|
||||
Value params{rapidjson::kObjectType};
|
||||
params.AddMember("userIP", ip, alloc);
|
||||
params.AddMember("appVer", "v.0.0.1", alloc); /// TODO add version to cmake
|
||||
params.AddMember("os", os, alloc);
|
||||
params.AddMember("os", osNamePretty, alloc);
|
||||
|
||||
coreRequest.AddMember("params", std::move(params), alloc);
|
||||
}
|
||||
|
||||
18
PAM/ssh/include/rublon/method/PUSH.hpp
Normal file
18
PAM/ssh/include/rublon/method/PUSH.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <rublon/authentication_step_interface.hpp>
|
||||
#include <rublon/pam.hpp>
|
||||
#include <rublon/pam_action.hpp>
|
||||
|
||||
#include <rublon/method/websocket_based_auth.hpp>
|
||||
|
||||
namespace rublon::method {
|
||||
|
||||
class PUSH : public WebsocketBasedAuth {
|
||||
public:
|
||||
PUSH(std::string systemToken, std::string tid) : WebsocketBasedAuth(std::move(systemToken), std::move(tid), "PUSH") {}
|
||||
};
|
||||
|
||||
} // namespace rublon::method
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include <rublon/method/OTP.hpp>
|
||||
#include <rublon/method/SMS.hpp>
|
||||
#include <rublon/method/PUSH.hpp>
|
||||
|
||||
template < class F >
|
||||
struct return_type;
|
||||
@ -55,7 +56,7 @@ class MethodProxy {
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant< method::OTP, method::SMS > _impl;
|
||||
std::variant< method::OTP, method::SMS, method::PUSH > _impl;
|
||||
};
|
||||
|
||||
class PostMethod : public rublon::AuthenticationStep< PostMethod > {
|
||||
@ -72,6 +73,8 @@ class PostMethod : public rublon::AuthenticationStep< PostMethod > {
|
||||
return MethodProxy{method::OTP{this->_systemToken, std::move(tid)}};
|
||||
} else if(_method == "sms") {
|
||||
return MethodProxy{method::SMS{this->_systemToken, std::move(tid)}};
|
||||
} else if(_method == "push"){
|
||||
return MethodProxy{method::PUSH{this->_systemToken, std::move(tid)}};
|
||||
}
|
||||
|
||||
else
|
||||
@ -147,16 +150,24 @@ class MethodSelect {
|
||||
if(method == "totp") {
|
||||
logMethodAvailable(method);
|
||||
pam.print("%d: Mobile TOTP", i + 1);
|
||||
methods_id[++i] = "totp";
|
||||
methods_id[++i] = method;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(method == "sms") {
|
||||
logMethodAvailable(method);
|
||||
pam.print("%d: SMS code", i + 1);
|
||||
methods_id[++i] = "sms";
|
||||
methods_id[++i] = method;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(method == "push" ){
|
||||
logMethodAvailable(method);
|
||||
pam.print("%d: Mobile PUSH", i + 1);
|
||||
methods_id[++i] = method;
|
||||
continue;
|
||||
}
|
||||
|
||||
logMethodNotAvailable(method);
|
||||
}
|
||||
};
|
||||
|
||||
36
PAM/ssh/include/rublon/method/websocket_based_auth.hpp
Normal file
36
PAM/ssh/include/rublon/method/websocket_based_auth.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <rublon/authentication_step_interface.hpp>
|
||||
#include <rublon/pam.hpp>
|
||||
#include <rublon/pam_action.hpp>
|
||||
|
||||
#include <rublon/websockets.hpp>
|
||||
|
||||
namespace rublon::method {
|
||||
|
||||
class WebsocketBasedAuth : public AuthenticationStep< WebsocketBasedAuth > {
|
||||
using base_t = AuthenticationStep< WebsocketBasedAuth >;
|
||||
|
||||
public:
|
||||
const char * name = "";
|
||||
|
||||
WebsocketBasedAuth(std::string systemToken, std::string tid, const char * name)
|
||||
: base_t(std::move(systemToken), std::move(tid)), name{name} {}
|
||||
|
||||
template < typename Hander_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< AuthenticationStatus, Error > handle(const CoreHandlerInterface< Hander_t > & /*coreHandler*/,
|
||||
const PamInfo_t & pam) const {
|
||||
log(LogLevel::Info, "starting WS");
|
||||
|
||||
WebSocket ws;
|
||||
pam.print("Waiting for user approval");
|
||||
auto aproved = ws.connect(this->_tid);
|
||||
|
||||
return aproved ? AuthenticationStatus{AuthenticationStatus::Action::Confirmed} :
|
||||
AuthenticationStatus{AuthenticationStatus::Action::Denied};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rublon::method
|
||||
@ -45,14 +45,12 @@ class LinuxPam {
|
||||
void print(const char * fmt, Ti... ti) const noexcept {
|
||||
log(LogLevel::Debug, fmt, std::forward< Ti >(ti)...);
|
||||
pam_prompt(pamh, PAM_TEXT_INFO, nullptr, fmt, std::forward< Ti >(ti)...);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
template < typename Fun, typename... Ti >
|
||||
auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept {
|
||||
char * response = nullptr;
|
||||
pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &response, fmt, std::forward< Ti >(ti)...);
|
||||
sleep(1);
|
||||
if(response) {
|
||||
auto ret = f(response);
|
||||
free(response);
|
||||
|
||||
@ -30,12 +30,12 @@ class RublonBase {
|
||||
|
||||
|
||||
|
||||
int authenticate() {
|
||||
std::byte sharedMemory[32 * 1024] = {};
|
||||
std::pmr::monotonic_buffer_resource mr{sharedMemory, std::size(sharedMemory)};
|
||||
std::pmr::unsynchronized_pool_resource rublonPoolResource{&mr};
|
||||
std::pmr::set_default_resource(&rublonPoolResource);
|
||||
}
|
||||
// int authenticate() {
|
||||
// std::byte sharedMemory[32 * 1024] = {};
|
||||
// std::pmr::monotonic_buffer_resource mr{sharedMemory, std::size(sharedMemory)};
|
||||
// std::pmr::unsynchronized_pool_resource rublonPoolResource{&mr};
|
||||
// std::pmr::set_default_resource(&rublonPoolResource);
|
||||
// }
|
||||
};
|
||||
|
||||
} // namespace rublon
|
||||
|
||||
@ -128,15 +128,15 @@ constexpr LogLevel g_level = LogLevel::Debug;
|
||||
constexpr bool syncLogFile = true;
|
||||
|
||||
namespace details {
|
||||
|
||||
constexpr const char * logPath() {
|
||||
constexpr auto path = "/var/log/rublon-ssh.log";
|
||||
constexpr auto path = "/tmp/rublon-ssh.log";
|
||||
return path;
|
||||
}
|
||||
|
||||
static void doLog(LogLevel level, const char * line) noexcept {
|
||||
auto fp = std::unique_ptr< FILE, int (*)(FILE *) >(fopen(logPath(), "a"), fclose);
|
||||
if(fp) {
|
||||
///TODO add transaction ID
|
||||
fprintf(fp.get(), "%s [%s] %s\n", dateStr().data(), LogLevelNames[( int ) level], line);
|
||||
if(syncLogFile)
|
||||
sync();
|
||||
|
||||
245
PAM/ssh/include/rublon/websockets.hpp
Normal file
245
PAM/ssh/include/rublon/websockets.hpp
Normal file
@ -0,0 +1,245 @@
|
||||
#pragma once
|
||||
|
||||
#include <rublon/utils.hpp>
|
||||
|
||||
#include <sio_client.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace rublon {
|
||||
#define SERVER_ADDRESS "wss://staging-core.rublon.net/ws/socket.io"
|
||||
#define TIMEOUT_SECONDS 90
|
||||
|
||||
/// {"status":"ERROR","code":400,"result":{"exception":"MobileAppMissingException","code":32,"errorMessage":"No mobile app
|
||||
/// detected","details":null}}
|
||||
|
||||
class WebSocketConnectionListener {
|
||||
public:
|
||||
enum class Status { Disconnected, Conected };
|
||||
|
||||
private:
|
||||
sio::client & _ws;
|
||||
|
||||
std::mutex & _lock;
|
||||
std::condition_variable_any & _cond;
|
||||
|
||||
bool handshake{false};
|
||||
Status _status{Status::Disconnected};
|
||||
|
||||
public:
|
||||
WebSocketConnectionListener(sio::client & ws, std::mutex & lock, std::condition_variable_any & cond)
|
||||
: _ws(ws), _lock{lock}, _cond{cond} {
|
||||
_ws.set_open_listener([this]() { this->on_connected(); });
|
||||
_ws.set_close_listener([this](sio::client::close_reason const & reason) { this->on_close(reason); });
|
||||
_ws.set_fail_listener([this]() { this->on_fail(); });
|
||||
}
|
||||
|
||||
tl::expected< Status, bool > waitForConnection() {
|
||||
std::lock_guard lock{_lock};
|
||||
if(!handshake) {
|
||||
log(LogLevel::Info, "Waiting for connection");
|
||||
_cond.wait(_lock);
|
||||
log(LogLevel::Info, "Connection OK!");
|
||||
}
|
||||
|
||||
return _status;
|
||||
}
|
||||
|
||||
void on_connected() {
|
||||
std::unique_lock{_lock};
|
||||
log(LogLevel::Info, "WebSocket connection estamblished");
|
||||
handshake = true;
|
||||
_status = Status::Conected;
|
||||
_cond.notify_all();
|
||||
}
|
||||
|
||||
void on_close(sio::client::close_reason const & reason) {
|
||||
std::unique_lock{_lock};
|
||||
log(LogLevel::Info,
|
||||
"WebSocket connection %s",
|
||||
reason == sio::client::close_reason::close_reason_drop ? "dropped" : "closed normally");
|
||||
handshake = true;
|
||||
_status = Status::Disconnected;
|
||||
_cond.notify_all();
|
||||
}
|
||||
|
||||
void on_fail() {
|
||||
std::unique_lock{_lock};
|
||||
log(LogLevel::Info, "WebSocket connection failed");
|
||||
handshake = true;
|
||||
_status = Status::Disconnected;
|
||||
_cond.notify_all();
|
||||
}
|
||||
};
|
||||
|
||||
class WebSocketSingleShotEventListener {
|
||||
public:
|
||||
enum class Status { Approved, Denied, Expired };
|
||||
|
||||
private:
|
||||
sio::client & _ws;
|
||||
|
||||
std::mutex & _lock;
|
||||
std::condition_variable_any & _cond;
|
||||
|
||||
bool event_received = false;
|
||||
Status _status{};
|
||||
|
||||
void printobj (std::size_t i, const std::map< std::string, sio::message::ptr > & objects) {
|
||||
for(const auto &[name, msg]:objects){
|
||||
log(LogLevel::Debug, "Object %ld: %s", i, name.c_str());
|
||||
printMessage(i, msg);
|
||||
}
|
||||
};
|
||||
void printMessage (std::size_t i, const sio::message::ptr & message) {
|
||||
switch(message->get_flag()) {
|
||||
case sio::message::flag_integer:
|
||||
log(LogLevel::Debug, "message %ld integer : %d", i, message->get_int());
|
||||
break;
|
||||
case sio::message::flag_double:
|
||||
log(LogLevel::Debug, "message %ld double : %f", i, message->get_double());
|
||||
break;
|
||||
case sio::message::flag_string:
|
||||
log(LogLevel::Debug, "message %ld string : %s", i, message->get_string().c_str());
|
||||
break;
|
||||
case sio::message::flag_binary:
|
||||
log(LogLevel::Debug, "message %ld binary : %s", i, message->get_binary()->c_str());
|
||||
break;
|
||||
case sio::message::flag_array:
|
||||
log(LogLevel::Debug, "message %ld array : blah", i);
|
||||
break;
|
||||
case sio::message::flag_object:
|
||||
log(LogLevel::Debug, "message %ld object : obj ->", i);
|
||||
printobj(i, message->get_map());
|
||||
break;
|
||||
case sio::message::flag_boolean:
|
||||
log(LogLevel::Debug, "message %ld bool : %s", i, message->get_bool() ? "yes" : "no");
|
||||
break;
|
||||
case sio::message::flag_null:
|
||||
log(LogLevel::Debug, "message %ld NULL", i);
|
||||
break;
|
||||
default:
|
||||
log(LogLevel::Info, "Message with unknown type");
|
||||
}
|
||||
};
|
||||
|
||||
void generic(sio::event & e, Status status) {
|
||||
std::lock_guard lock{_lock};
|
||||
event_received = true;
|
||||
_status = status;
|
||||
|
||||
log(LogLevel::Debug, "event name : %s", e.get_name().c_str());
|
||||
log(LogLevel::Debug, "event nsp : %s", e.get_nsp().c_str());
|
||||
log(LogLevel::Debug, "event messages: %d", e.get_messages().size());
|
||||
|
||||
|
||||
for(std::size_t i = 0; i < e.get_messages().size(); i++) {
|
||||
const auto & message = e.get_messages().at(i);
|
||||
printMessage(i, message);
|
||||
}
|
||||
|
||||
_cond.notify_all();
|
||||
}
|
||||
|
||||
void onConfirmed(sio::event & e) {
|
||||
generic(e, Status::Approved);
|
||||
log(LogLevel::Info, "Autentication confirmed over PUSH");
|
||||
}
|
||||
|
||||
void onDenied(sio::event & e) {
|
||||
generic(e, Status::Denied);
|
||||
log(LogLevel::Info, "Autentication denied by user");
|
||||
sleep(30);
|
||||
}
|
||||
|
||||
void onExpired(sio::event & e) {
|
||||
generic(e, Status::Expired);
|
||||
log(LogLevel::Error, "Autentication call expierd");
|
||||
}
|
||||
|
||||
void onErrorEvent(sio::message::ptr const & message) {
|
||||
std::lock_guard lock{_lock};
|
||||
event_received = true;
|
||||
log(LogLevel::Error, "Error: %s", message->get_string().c_str());
|
||||
_cond.notify_all();
|
||||
}
|
||||
|
||||
void onAny(sio::event & e) {
|
||||
std::lock_guard lock{_lock};
|
||||
event_received = true;
|
||||
log(LogLevel::Info, "name %s", e.get_name().c_str());
|
||||
_cond.notify_all();
|
||||
}
|
||||
|
||||
public:
|
||||
WebSocketSingleShotEventListener(sio::client & ws, std::mutex & lock, std::condition_variable_any & cond)
|
||||
: _ws{ws}, _lock{lock}, _cond{cond} {
|
||||
_ws.socket()->on("transactionConfirmed", [this](sio::event & e) { this->onConfirmed(e); });
|
||||
_ws.socket()->on("transactionDenied", [this](sio::event & e) { this->onDenied(e); });
|
||||
_ws.socket()->on("transactionExpired", [this](sio::event & e) { this->onExpired(e); });
|
||||
|
||||
_ws.socket()->on_error([this](sio::message::ptr const & message) { this->onErrorEvent(message); });
|
||||
_ws.socket()->on_any([this](sio::event & e) { this->onAny(e); });
|
||||
}
|
||||
|
||||
tl::expected< Status, bool > waitForEvent() {
|
||||
std::lock_guard lock{_lock};
|
||||
if(!event_received) {
|
||||
log(LogLevel::Info, "Waiting for confirmation");
|
||||
if(_cond.wait_until(_lock, std::chrono::system_clock::now() + std::chrono::minutes{2}) == std::cv_status::timeout) {
|
||||
log(LogLevel::Info, "Waiting for confirmation failed due to WS timeout");
|
||||
}
|
||||
}
|
||||
|
||||
return _status;
|
||||
}
|
||||
};
|
||||
|
||||
class WebSocket {
|
||||
sio::client ws;
|
||||
|
||||
public:
|
||||
std::string token;
|
||||
|
||||
WebSocket() {}
|
||||
|
||||
~WebSocket() {}
|
||||
|
||||
bool connect(std::string _token) {
|
||||
std::mutex _lock;
|
||||
std::condition_variable_any _cond;
|
||||
|
||||
token = _token;
|
||||
// ws.set_logs_verbose();
|
||||
|
||||
log(LogLevel::Debug, "start listening");
|
||||
ws.connect("wss://staging-core.rublon.net/ws/socket.io/");
|
||||
|
||||
const auto attachToTransactionConfirmationChannel = [&](const auto & status) -> tl::expected< bool, bool > {
|
||||
/// TODO check status
|
||||
auto message = std::dynamic_pointer_cast< sio::object_message >(sio::object_message::create());
|
||||
message->insert("channel", "transactionConfirmation." + _token);
|
||||
ws.socket()->emit("subscribe", {message});
|
||||
|
||||
return true; /// TODO
|
||||
};
|
||||
|
||||
const auto waitForUserAction = [&](const auto & connected) -> tl::expected< WebSocketSingleShotEventListener::Status, bool > {
|
||||
WebSocketSingleShotEventListener eventListener{ws, _lock, _cond};
|
||||
return eventListener.waitForEvent();
|
||||
};
|
||||
|
||||
WebSocketConnectionListener l(ws, _lock, _cond);
|
||||
auto v = l.waitForConnection() //
|
||||
.and_then(attachToTransactionConfirmationChannel)
|
||||
.and_then(waitForUserAction)
|
||||
.value_or(WebSocketSingleShotEventListener::Status::Denied);
|
||||
|
||||
return v == WebSocketSingleShotEventListener::Status::Approved;
|
||||
}
|
||||
|
||||
void listen() {}
|
||||
};
|
||||
} // namespace rublon
|
||||
@ -31,13 +31,27 @@ target_link_libraries(rublon-ssh-pam
|
||||
-lcurl
|
||||
-lssl
|
||||
-lcrypto
|
||||
-lsioclient_tls
|
||||
)
|
||||
|
||||
execute_process (
|
||||
COMMAND bash -c "awk -F= '/^ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'"
|
||||
OUTPUT_VARIABLE outOS
|
||||
)
|
||||
|
||||
if(${outOS} MATCHES "centos|rhel" )
|
||||
message(INFO "detected rhen base system")
|
||||
set(_destination /usr/lib64/security/)
|
||||
elseif(${outOS} MATCHES "debian|ubuntu")
|
||||
message(INFO "detected debian based system")
|
||||
set(_destination /usr/lib/x86_64-linux-gnu/security/)
|
||||
endif()
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
rublon-ssh-pam
|
||||
DESTINATION
|
||||
/usr/lib/x86_64-linux-gnu/security/
|
||||
${_destination}
|
||||
COMPONENT
|
||||
PAM
|
||||
)
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <security/pam_ext.h>
|
||||
#include <security/pam_misc.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <rublon/init.hpp>
|
||||
#include <rublon/json.hpp>
|
||||
@ -12,8 +13,6 @@
|
||||
|
||||
#define DLL_PUBLIC __attribute__((visibility("default")))
|
||||
|
||||
using namespace std;
|
||||
|
||||
DLL_PUBLIC int pam_sm_setcred([[maybe_unused]] pam_handle_t * pamh,
|
||||
[[maybe_unused]] int flags,
|
||||
[[maybe_unused]] int argc,
|
||||
@ -32,6 +31,10 @@ DLL_PUBLIC int
|
||||
pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unused]] int argc, [[maybe_unused]] const char ** argv) {
|
||||
using namespace rublon;
|
||||
|
||||
rublon::log(LogLevel::Debug, "flags: {%d}, argc: {%d}", flags, argc);
|
||||
// std::freopen(rublon::details::logPath(), "a+", stdout);
|
||||
// std::freopen(rublon::details::logPath(), "a+", stderr);
|
||||
|
||||
LinuxPam pam{pamh};
|
||||
|
||||
auto rublonConfig = ConfigurationFactory{}.systemConfig();
|
||||
@ -72,22 +75,20 @@ pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unu
|
||||
pam.print("\n RUBLON authentication bypased");
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
if(error.is< HttpError >()){
|
||||
|
||||
if(error.is< HttpError >()) {
|
||||
pam.print("\n RUBLON server unavalible");
|
||||
if(rublonConfig->parameters.bypass ){
|
||||
if(rublonConfig->parameters.bypass) {
|
||||
pam.print("\n RUBLON authentication bypased");
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
pam.print("RUBLON authentication FAILED");
|
||||
return PAM_MAXTRIES;
|
||||
}
|
||||
}
|
||||
|
||||
if(error.is<CoreHandlerError>()){
|
||||
pam.print("\n RUBLON server returned '%s' exception",
|
||||
error.get<CoreHandlerError>().reson.c_str());
|
||||
|
||||
if(error.is< CoreHandlerError >()) {
|
||||
pam.print("\n RUBLON server returned '%s' exception", error.get< CoreHandlerError >().reson.c_str());
|
||||
}
|
||||
pam.print("RUBLON authentication FAILED");
|
||||
rublon::log(LogLevel::Warning, "User login failed");
|
||||
|
||||
@ -44,4 +44,7 @@ static constexpr const char * result_broken_template = //
|
||||
static constexpr const char * wrongPasscode = //
|
||||
R"json({"status":"OK","result":{"error":"Hmm, that's not the right code. Try again."}})json";
|
||||
|
||||
static constexpr const char * projectError =
|
||||
R"json({"status":"ERROR","code":400,"result":{"exception":"APIException","code":10,"errorMessage":"Project error","details":null}})json";
|
||||
|
||||
} // namespace
|
||||
|
||||
30
os/centos/stream9/Vagrantfile
vendored
30
os/centos/stream9/Vagrantfile
vendored
@ -15,7 +15,7 @@ Vagrant.configure("2") do |config|
|
||||
# Bridged networks make the machine appear as another physical device on
|
||||
# your network.
|
||||
config.vm.network "public_network"
|
||||
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# the path on the host to the actual folder. The second argument is
|
||||
# the path on the guest to mount the folder. And the optional third
|
||||
@ -36,7 +36,18 @@ Vagrant.configure("2") do |config|
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
|
||||
yum update
|
||||
yum install -y gcc openssl-devel curl-devel pam-devel git rapidjson-devel cmake
|
||||
yum install -y gcc openssl-devel curl-devel pam-devel git rapidjson-devel cmake policycoreutils-devel checkpolicy
|
||||
|
||||
# get dependencies
|
||||
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
|
||||
mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --target install
|
||||
|
||||
#handle semodule
|
||||
cd /home/vagrant/Rublon-Linux/service
|
||||
checkmodule -M -m -o login_rublon.mod login_rublon.te
|
||||
semodule_package -o login_rublon.pp -m login_rublon.mod
|
||||
|
||||
# Build project
|
||||
cd /home/vagrant/Rublon-Linux
|
||||
@ -46,11 +57,18 @@ Vagrant.configure("2") do |config|
|
||||
sudo cmake --install build
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
#handle semodule
|
||||
cd /home/vagrant/Rublon-Linux/service
|
||||
semodule -i login_rublon.pp
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
#grep -q -e '#auth substack password-auth' /etc/pam.d/sshd || sed -i -e 's/auth substack password-auth/#auth substack password-auth/g' /etc/pam.d/sshd
|
||||
#grep -q -e 'auth requisite pam_unix.so' /etc/pam.d/sshd || sed -i '\$aauth requisite pam_unix.so' /etc/pam.d/sshd
|
||||
#grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
#grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
systemctl restart sshd.service
|
||||
SHELL
|
||||
|
||||
26
os/debian/11/Vagrantfile
vendored
26
os/debian/11/Vagrantfile
vendored
@ -23,6 +23,8 @@ Vagrant.configure("2") do |config|
|
||||
config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux"
|
||||
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
vb.memory = 1024
|
||||
vb.cpus = 4
|
||||
# Display the VirtualBox GUI when booting the machine
|
||||
vb.gui = true
|
||||
|
||||
@ -47,6 +49,12 @@ Vagrant.configure("2") do |config|
|
||||
rapidjson-dev \
|
||||
cmake
|
||||
|
||||
# get dependencies
|
||||
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
|
||||
mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --target install
|
||||
|
||||
# Build project
|
||||
cd /home/vagrant/Rublon-Linux
|
||||
cmake -B build && cmake --build build
|
||||
@ -56,11 +64,21 @@ Vagrant.configure("2") do |config|
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
SSHD_CONF=/etc/ssh/sshd_config
|
||||
SSHD_PAM_CONF=/etc/pam.d/sshd
|
||||
|
||||
grep -qe "^PasswordAuthentication" $SSHD_CONF && sed -i 's/^#*PasswordAuthentication[[:space:]]\+.*/PasswordAuthentication yes/' $SSHD_CONF || echo "PasswordAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^ChallengeResponseAuthentication" $SSHD_CONF && sed -i 's/^#*ChallengeResponseAuthentication[[:space:]]\+.*/ChallengeResponseAuthentication yes/' $SSHD_CONF || echo "ChallengeResponseAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^UsePAM" $SSHD_CONF && sed -i 's/^#*UsePAM[[:space:]]\+.*/UsePAM yes/' $SSHD_CONF || echo "UsePAM yes" >> $SSHD_CONF
|
||||
|
||||
grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aauth required pam_rublon.so' $SSHD_PAM_CONF
|
||||
grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aaccount required pam_rublon.so' $SSHD_PAM_CONF
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
service sshd restart
|
||||
SHELL
|
||||
|
||||
config.vm.provision "file", source: "/etc/rublon.config", destination: "/etc/rublon.config"
|
||||
end
|
||||
|
||||
16
os/debian/12/Vagrantfile
vendored
16
os/debian/12/Vagrantfile
vendored
@ -56,10 +56,18 @@ Vagrant.configure("2") do |config|
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
SSHD_CONF=/etc/ssh/sshd_config
|
||||
SSHD_PAM_CONF=/etc/pam.d/sshd
|
||||
|
||||
grep -qe "^PasswordAuthentication" $SSHD_CONF && sed -i 's/^#*PasswordAuthentication[[:space:]]\+.*/PasswordAuthentication yes/' $SSHD_CONF || echo "PasswordAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^ChallengeResponseAuthentication" $SSHD_CONF && sed -i 's/^#*ChallengeResponseAuthentication[[:space:]]\+.*/ChallengeResponseAuthentication yes/' $SSHD_CONF || echo "ChallengeResponseAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^UsePAM" $SSHD_CONF && sed -i 's/^#*UsePAM[[:space:]]\+.*/UsePAM yes/' $SSHD_CONF || echo "UsePAM yes" >> $SSHD_CONF
|
||||
|
||||
grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aauth required pam_rublon.so' $SSHD_PAM_CONF
|
||||
grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aaccount required pam_rublon.so' $SSHD_PAM_CONF
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
service sshd restart
|
||||
end
|
||||
|
||||
79
os/rhel/9/Vagrantfile
vendored
Executable file
79
os/rhel/9/Vagrantfile
vendored
Executable file
@ -0,0 +1,79 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Default user
|
||||
# ----------------------
|
||||
# login: vagrant
|
||||
# pass: vagrant
|
||||
Vagrant.configure("2") do |config|
|
||||
# Basic configuration
|
||||
config.vm.provider "virtualbox"
|
||||
config.vm.box = "generic/rhel9"
|
||||
config.ssh.forward_agent = true
|
||||
|
||||
# Create a public network, which generally matched to bridged network.
|
||||
# Bridged networks make the machine appear as another physical device on
|
||||
# your network.
|
||||
config.vm.network "public_network"
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# the path on the host to the actual folder. The second argument is
|
||||
# the path on the guest to mount the folder. And the optional third
|
||||
# argument is a set of non-required options.
|
||||
config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux"
|
||||
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
vb.memory = 1024
|
||||
vb.cpus = 4
|
||||
# Display the VirtualBox GUI when booting the machine
|
||||
vb.gui = true
|
||||
|
||||
# Fix for 'SSH auth method: Private key' stuck
|
||||
vb.customize ["modifyvm", :id, "--cableconnected1", "on"]
|
||||
end
|
||||
|
||||
# Enable provisioning with a shell script. Additional provisioners such as
|
||||
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
|
||||
# documentation for more information about their specific syntax and use.
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
|
||||
yum update
|
||||
yum install -y gcc openssl-devel curl-devel pam-devel git rapidjson-devel cmake
|
||||
|
||||
# get dependencies
|
||||
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
|
||||
mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --target install
|
||||
|
||||
#handle semodule
|
||||
cd /home/vagrant/Rublon-Linux/service
|
||||
checkmodule -M -m -o login_rublon.mod login_rublon.te
|
||||
semodule_package -o login_rublon.pp -m login_rublon.mod
|
||||
|
||||
# Build project
|
||||
cd /home/vagrant/Rublon-Linux
|
||||
cmake -B build && cmake --build build
|
||||
# Install
|
||||
sudo cmake --install build
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
#handle semodule
|
||||
cd /home/vagrant/Rublon-Linux/service
|
||||
semodule -i login_rublon.pp
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
systemctl restart sshd.service
|
||||
SHELL
|
||||
|
||||
config.vm.provision "file", source: "/etc/rublon.config", destination: "/etc/rublon.config"
|
||||
end
|
||||
|
||||
22
os/ubuntu/20.04/Vagrantfile
vendored
22
os/ubuntu/20.04/Vagrantfile
vendored
@ -46,6 +46,12 @@ Vagrant.configure("2") do |config|
|
||||
git \
|
||||
rapidjson-dev \
|
||||
cmake
|
||||
|
||||
# get dependencies
|
||||
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
|
||||
mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --target install
|
||||
|
||||
# Build project
|
||||
cd /home/vagrant/Rublon-Linux
|
||||
@ -56,10 +62,18 @@ Vagrant.configure("2") do |config|
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
SSHD_CONF=/etc/ssh/sshd_config
|
||||
SSHD_PAM_CONF=/etc/pam.d/sshd
|
||||
|
||||
grep -qe "^PasswordAuthentication" $SSHD_CONF && sed -i 's/^#*PasswordAuthentication[[:space:]]\+.*/PasswordAuthentication yes/' $SSHD_CONF || echo "PasswordAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^ChallengeResponseAuthentication" $SSHD_CONF && sed -i 's/^#*ChallengeResponseAuthentication[[:space:]]\+.*/ChallengeResponseAuthentication yes/' $SSHD_CONF || echo "ChallengeResponseAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^UsePAM" $SSHD_CONF && sed -i 's/^#*UsePAM[[:space:]]\+.*/UsePAM yes/' $SSHD_CONF || echo "UsePAM yes" >> $SSHD_CONF
|
||||
|
||||
grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aauth required pam_rublon.so' $SSHD_PAM_CONF
|
||||
grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aaccount required pam_rublon.so' $SSHD_PAM_CONF
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
service sshd restart
|
||||
SHELL
|
||||
|
||||
22
os/ubuntu/22.04/Vagrantfile
vendored
22
os/ubuntu/22.04/Vagrantfile
vendored
@ -47,6 +47,12 @@ Vagrant.configure("2") do |config|
|
||||
rapidjson-dev \
|
||||
cmake
|
||||
|
||||
# get dependencies
|
||||
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
|
||||
mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --target install
|
||||
|
||||
# Build project
|
||||
cd /home/vagrant/Rublon-Linux
|
||||
cmake -B build && cmake --build build
|
||||
@ -56,10 +62,18 @@ Vagrant.configure("2") do |config|
|
||||
sudo install -m 644 rsc/rublon.config.defaults /etc/rublon.config
|
||||
|
||||
# Register Rublon pam
|
||||
sed -i 's/UsePAM .*/UsePAM yes/' /etc/ssh/sshd_config
|
||||
sed -i 's/ChallengeResponseAuthentication .*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||
grep -q -e 'auth required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aauth required pam_rublon.so' /etc/pam.d/sshd
|
||||
grep -q -e 'account required pam_rublon.so' /etc/pam.d/sshd || sed -i '\$aaccount required pam_rublon.so' /etc/pam.d/sshd
|
||||
SSHD_CONF=/etc/ssh/sshd_config
|
||||
SSHD_PAM_CONF=/etc/pam.d/sshd
|
||||
|
||||
grep -qe "^PasswordAuthentication" $SSHD_CONF && sed -i 's/^#*PasswordAuthentication[[:space:]]\+.*/PasswordAuthentication yes/' $SSHD_CONF || echo "PasswordAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^ChallengeResponseAuthentication" $SSHD_CONF && sed -i 's/^#*ChallengeResponseAuthentication[[:space:]]\+.*/ChallengeResponseAuthentication yes/' $SSHD_CONF || echo "ChallengeResponseAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^UsePAM" $SSHD_CONF && sed -i 's/^#*UsePAM[[:space:]]\+.*/UsePAM yes/' $SSHD_CONF || echo "UsePAM yes" >> $SSHD_CONF
|
||||
|
||||
grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aauth required pam_rublon.so' $SSHD_PAM_CONF
|
||||
grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aaccount required pam_rublon.so' $SSHD_PAM_CONF
|
||||
|
||||
useradd -s /bin/bash -m bwi
|
||||
echo "bwi:bwi"|chpasswd
|
||||
|
||||
service sshd restart
|
||||
SHELL
|
||||
|
||||
@ -29,6 +29,9 @@ set(CPACK_DEB_COMPONENT_INSTALL YES)
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS YES)
|
||||
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "libcurl(>= 7.0.0), libc(>= 2.0)")
|
||||
# set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "libcurl4(>= 7.0.0), libc(>= 2.0)")
|
||||
# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libcurl4(>= 7.0.0), libc(>= 2.0)")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/service/postinst")
|
||||
|
||||
include(CPack)
|
||||
|
||||
BIN
service/login_rublon.mod
Normal file
BIN
service/login_rublon.mod
Normal file
Binary file not shown.
BIN
service/login_rublon.pp
Normal file
BIN
service/login_rublon.pp
Normal file
Binary file not shown.
12
service/login_rublon.te
Normal file
12
service/login_rublon.te
Normal file
@ -0,0 +1,12 @@
|
||||
module login_rublon 1.0;
|
||||
require {
|
||||
type http_port_t;
|
||||
type soundd_port_t;
|
||||
type http_cache_port_t;
|
||||
type sshd_t;
|
||||
type unreserved_port_t;
|
||||
class tcp_socket name_connect;
|
||||
class udp_socket name_bind;
|
||||
};
|
||||
allow sshd_t {http_port_t http_cache_port_t soundd_port_t}:tcp_socket name_connect;
|
||||
allow sshd_t {unreserved_port_t}:udp_socket name_bind;
|
||||
27
service/postinst
Normal file
27
service/postinst
Normal file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
if [ ! -f /etc/rublon/rublon.config ]
|
||||
then
|
||||
mkdir -p /etc/rublon
|
||||
cp -a /usr/share/rublon/rublon.config.defaults /etc/rublon/rublon.config
|
||||
fi
|
||||
|
||||
# get system id
|
||||
. /etc/os-release
|
||||
|
||||
SSHD_CONF=/etc/ssh/sshd_config
|
||||
SSHD_PAM_CONF=/etc/pam.d/sshd
|
||||
|
||||
grep -qe "^PasswordAuthentication" $SSHD_CONF && \
|
||||
sed -i 's/^#*PasswordAuthentication[[:space:]]\+.*/PasswordAuthentication yes/' $SSHD_CONF || \
|
||||
echo "PasswordAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^ChallengeResponseAuthentication" $SSHD_CONF && \
|
||||
sed -i 's/^#*ChallengeResponseAuthentication[[:space:]]\+.*/ChallengeResponseAuthentication yes/' $SSHD_CONF || \
|
||||
echo "ChallengeResponseAuthentication yes" >> $SSHD_CONF
|
||||
grep -qe "^UsePAM" $SSHD_CONF && \
|
||||
sed -i 's/^#*UsePAM[[:space:]]\+.*/UsePAM yes/' $SSHD_CONF || \
|
||||
echo "UsePAM yes" >> $SSHD_CONF
|
||||
|
||||
grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aauth required pam_rublon.so' $SSHD_PAM_CONF
|
||||
grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '\$aaccount required pam_rublon.so' $SSHD_PAM_CONF
|
||||
Loading…
Reference in New Issue
Block a user