aboutsummaryrefslogtreecommitdiff
path: root/src/npassd
diff options
context:
space:
mode:
authorsinanmohd <sinan@sinanmohd.com>2024-04-20 19:08:55 +0530
committersinanmohd <sinan@sinanmohd.com>2024-04-20 21:26:22 +0530
commit243c88e20bad08a7b2fe268cec3a7b5129f461a2 (patch)
treedf8b1c8c6eb3cb62745d32c637f5a78d94aa2ecf /src/npassd
parent47e0d63e931d14c91635abda4a7736f9e9b987c3 (diff)
npassd: init
Diffstat (limited to 'src/npassd')
-rw-r--r--src/npassd/meson.build15
-rw-r--r--src/npassd/npassd.c63
-rw-r--r--src/npassd/service.c77
-rw-r--r--src/npassd/session.c81
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;
+}