diff options
author | sinanmohd <sinan@sinanmohd.com> | 2024-04-20 19:08:55 +0530 |
---|---|---|
committer | sinanmohd <sinan@sinanmohd.com> | 2024-04-20 21:26:22 +0530 |
commit | 243c88e20bad08a7b2fe268cec3a7b5129f461a2 (patch) | |
tree | df8b1c8c6eb3cb62745d32c637f5a78d94aa2ecf /src/npassd | |
parent | 47e0d63e931d14c91635abda4a7736f9e9b987c3 (diff) |
npassd: init
Diffstat (limited to 'src/npassd')
-rw-r--r-- | src/npassd/meson.build | 15 | ||||
-rw-r--r-- | src/npassd/npassd.c | 63 | ||||
-rw-r--r-- | src/npassd/service.c | 77 | ||||
-rw-r--r-- | src/npassd/session.c | 81 |
4 files changed, 236 insertions, 0 deletions
diff --git a/src/npassd/meson.build b/src/npassd/meson.build new file mode 100644 index 0000000..10302cd --- /dev/null +++ b/src/npassd/meson.build @@ -0,0 +1,15 @@ +e = executable( + 'npassd', + [ + 'npassd.c', + 'service.c', + 'session.c', + ], + + include_directories: npass_inc, + dependencies: sdbus_dep, + link_with: lib_npass, + install: true, +) + +test('npassd', e) diff --git a/src/npassd/npassd.c b/src/npassd/npassd.c new file mode 100644 index 0000000..a2f5173 --- /dev/null +++ b/src/npassd/npassd.c @@ -0,0 +1,63 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <systemd/sd-bus.h> + +#include "npassd/service.h" +#include "util.h" + +#define DBUS_WELL_KNOWN_NAME "org.freedesktop.secrets" + +int main(void) +{ + int ret; + sd_bus *bus; + struct service service; + + ret = sd_bus_open_user(&bus); + if (ret < 0) { + print_err("Failed to connect to bus: %s", strerror(-ret)); + return EXIT_FAILURE; + } + + ret = sd_bus_request_name(bus, DBUS_WELL_KNOWN_NAME, 0); + if (ret < 0) { + print_err("Failed to acquire service name: %s", strerror(-ret)); + if (ret == -EEXIST) + print_err( + "%s", + "Is a secret-service daemon already running?"); + + goto out_free_bus; + } + + ret = service_init(bus, &service); + if (ret < 0) + goto out_free_bus; + + for (;;) { + ret = sd_bus_process(bus, NULL); + if (ret < 0) { + fprintf(stderr, "Failed to process bus: %s\n", + strerror(-ret)); + goto out_free_service; + } + if (ret > 0) + continue; + + ret = sd_bus_wait(bus, UINT64_MAX); + if (ret < 0) { + fprintf(stderr, "Failed to wait on bus: %s\n", + strerror(-ret)); + goto out_free_service; + } + } + +out_free_service: + service_free(&service); +out_free_bus: + sd_bus_unref(bus); + + return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/npassd/service.c b/src/npassd/service.c new file mode 100644 index 0000000..5628e45 --- /dev/null +++ b/src/npassd/service.c @@ -0,0 +1,77 @@ +#include <errno.h> +#include <stdio.h> +#include <systemd/sd-bus.h> + +#include "npassd/common.h" +#include "npassd/service.h" +#include "util.h" + +#define SERVICE_IFACE "org.freedesktop.Secret.Service" + +static int handle_open_session(sd_bus_message *msg, void *data, + sd_bus_error *ret_error); + +static const sd_bus_vtable service_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("OpenSession", "sv", "vo", handle_open_session, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static int handle_open_session(sd_bus_message *msg, void *data, + sd_bus_error *ret_error) +{ + struct service *service = data; + int ret, session_slot_no; + char *algo; + + ret = sd_bus_message_read(msg, "s", &algo); + if (ret < 0) + return ret; + + ret = strcmp(algo, "plain"); + if (ret) { + sd_bus_error_set_const(ret_error, SD_BUS_ERROR_NOT_SUPPORTED, + "Unsupported encryption algorithm"); + return -ENOTSUP; + } + + session_slot_no = session_slot_available(service->session, MAX_SESSION); + if (session_slot_no < 0) { + print_err("No free slot available: %s", + strerror(-session_slot_no)); + return ret; + } + + ret = session_new(service->bus, &service->session[session_slot_no], + session_slot_no); + if (ret < 0) + return ret; + + return sd_bus_reply_method_return( + msg, "vs", "s", "", service->session[session_slot_no].path); +} + +void service_free(struct service *service) +{ + for (int i = 0; i < MAX_SESSION; i++) + session_free(&service->session[i]); + + sd_bus_slot_unref(service->slot); +} + +int service_init(sd_bus *bus, struct service *service) +{ + int ret; + + service->bus = bus; + session_init(service->session, MAX_SESSION); + + ret = sd_bus_add_object_vtable(service->bus, &service->slot, + DBUS_OBJECT_PATH, SERVICE_IFACE, + service_vtable, service); + if (ret < 0) + print_err("Failed to connect to bus: %s", strerror(-ret)); + + return ret; +} diff --git a/src/npassd/session.c b/src/npassd/session.c new file mode 100644 index 0000000..e674bb7 --- /dev/null +++ b/src/npassd/session.c @@ -0,0 +1,81 @@ +#include <errno.h> +#include <linux/limits.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdio.h> +#include <systemd/sd-bus.h> + +#include "npassd/common.h" +#include "npassd/session.h" +#include "util.h" + +static int handle_close(__attribute__((unused)) sd_bus_message *msg, void *data, + __attribute__((unused)) sd_bus_error *ret_error); + +static const sd_bus_vtable session_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("Close", "", "", handle_close, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static int handle_close(__attribute__((unused)) sd_bus_message *msg, void *data, + __attribute__((unused)) sd_bus_error *ret_error) +{ + int ret; + + ret = session_free((struct session *)data); + if (ret < 0) + print_err("Failed to free session: %s", strerror(-ret)); + + return ret; +} + +int session_slot_available(struct session *s, size_t n) +{ + static pthread_mutex_t lock; + + pthread_mutex_lock(&lock); + for (size_t i = 0; i < n; i++) { + if (s[i].isactive == false) { + pthread_mutex_unlock(&lock); + return i; + } + } + + pthread_mutex_unlock(&lock); + return -ENOMEM; +} + +int session_new(sd_bus *bus, struct session *session, unsigned session_no) +{ + int ret; + + snprintf(session->path, sizeof(session->path), + DBUS_OBJECT_PATH "/session/%d", session_no); + ret = sd_bus_add_object_vtable(bus, &session->slot, session->path, + SESSION_IFACE, session_vtable, session); + if (ret < 0) + print_err("Failed to create session: %s", strerror(-ret)); + else + session->isactive = true; + + return ret; +} + +int session_free(struct session *s) +{ + if (!s->isactive) + return -EINVAL; + + s->isactive = false; + sd_bus_slot_unref(s->slot); + + return 0; +} + +void session_init(struct session *s, size_t n) +{ + for (size_t i = 0; i < n; i++) + s[i].isactive = false; +} |