Skip to content
Snippets Groups Projects
Commit dde37e5f authored by Leon Dietrich's avatar Leon Dietrich
Browse files

add: socket auth prototype

parent 035e32e0
No related branches found
No related tags found
No related merge requests found
#include "net/unix_socket_server.hpp"
#include <array>
#include <filesystem>
#include <sstream>
......@@ -21,7 +22,7 @@ std::string get_usocket_path(const socketaddr& addr) {
return std::string(((sockaddr_un*) addr.ptr())->sun_path);
}
auto_fd construct_server_fd(const socketaddr& addr) {
auto_fd construct_server_fd(const socketaddr& addr, bool use_explicit_authentication) {
if (addr.family() != AF_UNIX) {
throw netio_exception("Expected a UNIX socket file path.");
}
......@@ -51,13 +52,25 @@ auto_fd construct_server_fd(const socketaddr& addr) {
throw netio_exception(ss.str());
}
if(use_explicit_authentication) {
// TODO set SCM_CREDENTIALS
} else {
// FIXME SO_PASSCRED is platform specific (linux). For *BSD there are other APIs
int optval = 1;
if(setsockopt(socket_fd.get(), SOL_SOCKET, SO_PEERCRED, &optval, sizeof(optval)) == -1) {
unlink(get_usocket_path(addr).c_str());
throw netio_exception("Unable to enable password authentication for file socket. REASON: " + std::string(errno == EINVAL ? "EINVAL" : (errno == ENOPROTOOPT ? "ENOPROTOOPT" : "unexpected")));
// TODO might fail as not created with socketpair(). Check man2 socketpair
}
}
make_socket_nonblocking(socket_fd);
if (listen(socket_fd.get(), 5) == -1) {
// We already created the socket and close won't remove the file thus we need to unlink it.
unlink(get_usocket_path(addr).c_str());
throw netio_exception("Failed to enable listening mode for raw socket");
throw netio_exception("Failed to enable listening mode for raw socket.");
}
return socket_fd;
......@@ -65,8 +78,11 @@ auto_fd construct_server_fd(const socketaddr& addr) {
unix_socket_server::unix_socket_server(
const socketaddr &socket_identifier,
async_server_socket::accept_handler_type client_listener_
) : async_server_socket{construct_server_fd(socket_identifier)}, socket_path{get_usocket_path(socket_identifier)} {
async_server_socket::accept_handler_type client_listener_,
bool use_explicit_authentication
) : async_server_socket{construct_server_fd(socket_identifier, use_explicit_authentication)},
socket_path{get_usocket_path(socket_identifier)},
explicit_authentication{use_explicit_authentication} {
this->set_accept_handler(client_listener_);
}
......@@ -77,6 +93,10 @@ unix_socket_server::~unix_socket_server() {
}
}
constexpr size_t compute_required_msgh_buffer_size() {
return std::max(CMSG_SPACE(sizeof(ucred)), sizeof(cmsghdr));
}
std::shared_ptr<connection_client> unix_socket_server::await_raw_socket_incomming(const auto_fd& server_socket) {
auto client_socket = auto_fd{accept(server_socket.get(), nullptr, nullptr)};
......@@ -84,6 +104,39 @@ std::shared_ptr<connection_client> unix_socket_server::await_raw_socket_incommin
throw netio_exception("Failed to accept incomming client to unix socket.");
}
// Receive authentication data
// TODO this might be linux specific, we need to add support for other platforms
/*
// The code below should be multi platform compatible but is broken (heap buffer overflow)
msghdr msgh;
iovec iov;
std::array<char, compute_required_msgh_buffer_size()> msgBuf;
int data;
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
iov.iov_base = &data;
iov.iov_len = sizeof(data);
msgh.msg_control = msgBuf.data();
msgh.msg_controllen = sizeof(char) * sizeof(compute_required_msgh_buffer_size());
cmsghdr* cmsgp = CMSG_FIRSTHDR(&msgh);
if(cmsgp == nullptr || cmsgp->cmsg_len != CMSG_LEN(sizeof(ucred))) {
throw netio_exception("Received bad aux cmsg header in unix file socket.");
}
if(cmsgp->cmsg_level != SOL_SOCKET || cmsgp->cmsg_type != SCM_CREDENTIALS) {
throw netio_exception("Received wrong aux cmsg answer in unix file socket authentication.");
}
ucred destination_credential_storage;
memcpy(&destination_credential_storage, CMSG_DATA(cmsgp), sizeof(ucred));*/
ucred destination_credential_storage;
socklen_t len = sizeof(ucred);
if (getsockopt(client_socket.get(), SOL_SOCKET, SO_PEERCRED, &destination_credential_storage, &len) == -1) {
throw netio_exception("Failed to get peer authentication from incomming unix file socket client.");
}
make_socket_nonblocking(client_socket);
const socketaddr own_address{}, peer_address{};
......
......@@ -18,8 +18,9 @@ class unix_socket_server : public async_server_socket
{
private:
std::string socket_path;
bool explicit_authentication;
public:
unix_socket_server(const socketaddr& socket_identifier, async_server_socket::accept_handler_type client_listener_);
unix_socket_server(const socketaddr& socket_identifier, async_server_socket::accept_handler_type client_listener_, bool use_explicit_authentication = false);
virtual ~unix_socket_server();
public:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment