Skip to content

Commit

Permalink
added a separate password-hash generator executable, auth table popul…
Browse files Browse the repository at this point in the history
…ation from an auth-file
  • Loading branch information
catink123 committed Jan 17, 2024
1 parent b4ed56c commit a4cef8e
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ CPMAddPackage(
VERSION 2.0
GITHUB_REPOSITORY "hilch/Bcrypt.cpp"
GIT_TAG "V2.0_NODEBCRYPT"
OPTIONS
"BUILD_TESTS OFF"
)

add_subdirectory(${PROJECT_SOURCE_DIR}/src)
10 changes: 8 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_executable(
arduino_messenger.hpp
arduino_messenger.cpp
auth.hpp
auth.cpp
common_state.hpp
common_state.cpp
)
Expand All @@ -34,10 +35,15 @@ target_link_libraries(
bcrypt
)

# install server binary to bin
# password-hash generator
add_executable(password_hasher hash_generator.cpp)
set_property(TARGET password_hasher PROPERTY CXX_STANDARD 17)
target_link_libraries(password_hasher bcrypt)

# install the server binary and the password hasher to bin

install(
TARGETS ${PROJECT_NAME}
TARGETS ${PROJECT_NAME} password_hasher
RUNTIME DESTINATION bin
)

Expand Down
58 changes: 58 additions & 0 deletions src/auth.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "auth.hpp"

std::optional<std::unordered_map<std::string, auth_data>>
open_auth_table_from_file(fs::path file_path) {
std::ifstream file;
file.open(file_path);
if (!file.is_open()) {
return std::nullopt;
}

std::unordered_map<std::string, auth_data> auth_table;
std::string current_line;

// parsing line by line with the following format:
// login:permissions:password_hash
while (std::getline(file, current_line)) {
std::size_t first_delimeter = current_line.find(':');
if (first_delimeter == std::string::npos) {
continue;
}

std::size_t second_delimeter = current_line.find(':', first_delimeter + 1);
if (second_delimeter == std::string::npos || current_line.size() == second_delimeter) {
continue;
}

std::string login = current_line.substr(0, first_delimeter);
std::string permissions_str =
current_line.substr(
first_delimeter + 1,
second_delimeter - first_delimeter - 1
);
unsigned int permissions = 99;
try {
permissions = std::stoi(permissions_str);
}
catch (...) {
continue;
}
if (permissions > 2) {
continue;
}

std::string password_hash = current_line.substr(second_delimeter + 1);

auth_table.insert({
login,
auth_data(
static_cast<AuthorizationType>(permissions),
password_hash
)
});
}

file.close();

return auth_table;
}
19 changes: 10 additions & 9 deletions src/auth.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
#include <boost/beast/core/detail/base64.hpp>
#include <array>
#include <unordered_map>
#include <filesystem>
#include <fstream>

namespace base64 = beast::detail::base64;
namespace fs = std::filesystem;

enum AuthorizationType {
Control,
View,
Blocked
View = 0,
Control = 1,
Blocked = 2
};

const std::unordered_map<std::string, std::optional<AuthorizationType>> endpoint_map = {
Expand Down Expand Up @@ -59,12 +62,7 @@ struct auth_data {
) : permissions(permissions), password_hash(password_hash) {}
};

// catink123:testpassword123
// guest:guest
const std::unordered_map<std::string, auth_data> temp_auth_table = {
{ "catink123", auth_data(Control, "$2a$10$o12u27uUOjD6rJ0dlEE/EuL8EqGa7y8iwZqAp3wF0WBS4.Vu/9jhK") },
{ "guest", auth_data(View, "$2a$10$vYQHg8mBFTle1OzRp31MsOMvrmfQ52xfHUGFoi3aTe6Vp8GhDRzBy") }
};
typedef std::unordered_map<std::string, auth_data> auth_table_t;

template <class Body, class Allocator>
std::optional<AuthorizationType> get_auth(
Expand Down Expand Up @@ -110,4 +108,7 @@ std::optional<AuthorizationType> get_auth(
}
}

std::optional<std::unordered_map<std::string, auth_data>>
open_auth_table_from_file(fs::path file_path);

#endif
17 changes: 17 additions & 0 deletions src/hash_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <bcrypt.h>
#include <iostream>
#include <string>

int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Usage: %s <password-to-hash>", argv[0]);
return 1;
}

std::string password(argv[1]);
std::string password_hash = bcrypt::generateHash(password);

printf("%s", password_hash.c_str());

return 0;
}
9 changes: 6 additions & 3 deletions src/http_listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ http_listener::http_listener(
tcp::endpoint endpoint,
const std::shared_ptr<const std::string>& doc_root,
std::shared_ptr<common_state> comstate,
std::shared_ptr<arduino_messenger> arduino_connection
std::shared_ptr<arduino_messenger> arduino_connection,
std::shared_ptr<auth_table_t> auth_table
) : ioc(ioc),
acceptor(net::make_strand(ioc)),
doc_root(doc_root),
comstate(comstate),
arduino_connection(arduino_connection)
arduino_connection(arduino_connection),
auth_table(auth_table)
{
beast::error_code ec;

Expand Down Expand Up @@ -65,7 +67,8 @@ void http_listener::on_accept(beast::error_code ec, tcp::socket socket) {
std::move(socket),
doc_root,
comstate,
arduino_connection
arduino_connection,
auth_table
)->run();

do_accept();
Expand Down
4 changes: 3 additions & 1 deletion src/http_listener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ class http_listener : public std::enable_shared_from_this<http_listener> {
std::shared_ptr<const std::string> doc_root;
std::shared_ptr<common_state> comstate;
std::shared_ptr<arduino_messenger> arduino_connection;
std::shared_ptr<auth_table_t> auth_table;

public:
http_listener(
net::io_context& ioc,
tcp::endpoint endpoint,
const std::shared_ptr<const std::string>& doc_root,
std::shared_ptr<common_state> comstate,
std::shared_ptr<arduino_messenger> arduino_connection
std::shared_ptr<arduino_messenger> arduino_connection,
std::shared_ptr<auth_table_t> auth_table
);

void run();
Expand Down
15 changes: 9 additions & 6 deletions src/http_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ http_session::http_session(
tcp::socket&& socket,
const std::shared_ptr<const std::string>& doc_root,
std::shared_ptr<common_state> comstate,
std::shared_ptr<arduino_messenger> arduino_connection
std::shared_ptr<arduino_messenger> arduino_connection,
std::shared_ptr<auth_table_t> auth_table
) : stream(std::move(socket)),
doc_root(doc_root),
comstate(comstate),
arduino_connection(arduino_connection)
arduino_connection(arduino_connection),
auth_table(auth_table)
{
static_assert(queue_limit > 0, "queue limit must be non-zero and positive");
response_queue.reserve(queue_limit);
Expand Down Expand Up @@ -66,15 +68,15 @@ void http_session::on_read(
arduino_connection
);

session->do_accept(parser->release());
session->do_accept(parser->release(), auth_table);
comstate->add_session(session);

return;
}

// send the response back
queue_write(
handle_request(*doc_root, parser->release())
handle_request(*doc_root, parser->release(), auth_table)
);

// if the response queue is not at it's limit, try to add another response to the queue
Expand Down Expand Up @@ -189,7 +191,8 @@ beast::string_view mime_type(
template <class Body, class Allocator>
http::message_generator handle_request(
beast::string_view doc_root,
http::request<Body, http::basic_fields<Allocator>>&& req
http::request<Body, http::basic_fields<Allocator>>&& req,
std::shared_ptr<auth_table_t> auth_table
) {
const auto bad_request =
[&req] (beast::string_view why) {
Expand Down Expand Up @@ -296,7 +299,7 @@ http::message_generator handle_request(
return unauthorized(req.target());
}

const auto permissions = get_auth(req, temp_auth_table);
const auto permissions = get_auth(req, *auth_table);

if (!permissions) {
return unauthorized(req.target());
Expand Down
7 changes: 5 additions & 2 deletions src/http_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ const std::array<std::string, 3> indexable_endpoints = { "/", "/view", "/control
template <class Body, class Allocator>
http::message_generator handle_request(
beast::string_view doc_root,
http::request<Body, http::basic_fields<Allocator>>&& req
http::request<Body, http::basic_fields<Allocator>>&& req,
std::shared_ptr<auth_table_t> auth_table
);

class http_session : public std::enable_shared_from_this<http_session> {
Expand All @@ -39,6 +40,7 @@ class http_session : public std::enable_shared_from_this<http_session> {

std::shared_ptr<common_state> comstate;
std::shared_ptr<arduino_messenger> arduino_connection;
std::shared_ptr<auth_table_t> auth_table;

// a queue to prevent overload
static constexpr std::size_t queue_limit = 16;
Expand All @@ -51,7 +53,8 @@ class http_session : public std::enable_shared_from_this<http_session> {
tcp::socket&& socket,
const std::shared_ptr<const std::string>& doc_root,
std::shared_ptr<common_state> comstate,
std::shared_ptr<arduino_messenger> arduino_connection
std::shared_ptr<arduino_messenger> arduino_connection,
std::shared_ptr<auth_table_t> auth_table
);

void run();
Expand Down
26 changes: 23 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,30 @@ const auto DOC_ROOT = std::make_shared<std::string>("./client");
const auto THREAD_COUNT = 8;

int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Usage: %s <com-port>", argv[0]);
if (argc < 3) {
printf("Usage: %s <com-port> <auth-file>", argv[0]);
return 1;
}

fs::path auth_file_path;

try {
auth_file_path = argv[2];
}
catch (...) {
std::cerr << "Invalid auth-file path." << std::endl;
return 1;
}

auto auth_table = open_auth_table_from_file(auth_file_path);
if (!auth_table) {
std::cerr << "Couldn't open the supplied auth-file." << std::endl;
return 1;
}

std::shared_ptr<auth_table_t> auth_table_ptr =
std::make_shared<auth_table_t>(std::move(auth_table.value()));

net::io_context ioc{THREAD_COUNT};

try {
Expand All @@ -44,7 +63,8 @@ int main(int argc, char* argv[]) {
tcp::endpoint{ADDRESS, PORT},
DOC_ROOT,
comstate,
arduino_connection
arduino_connection,
auth_table_ptr
)->run();

std::cout << "Server started at " << ADDRESS << ":" << PORT << "." << std::endl;
Expand Down
5 changes: 3 additions & 2 deletions src/websocket_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ class websocket_session : public std::enable_shared_from_this<websocket_session>

template<class Body, class Allocator>
void do_accept(
http::request<Body, http::basic_fields<Allocator>> req
http::request<Body, http::basic_fields<Allocator>> req,
std::shared_ptr<auth_table_t> auth_table
) {
auto auth = get_auth(req, temp_auth_table);
auto auth = get_auth(req, *auth_table);
if (auth == std::nullopt || auth == Blocked) {
return;
}
Expand Down

0 comments on commit a4cef8e

Please sign in to comment.