aboutsummaryrefslogtreecommitdiff
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
parent47e0d63e931d14c91635abda4a7736f9e9b987c3 (diff)
npassd: init
-rw-r--r--README.md29
-rw-r--r--flake.nix13
-rw-r--r--include/npassd/common.h1
-rw-r--r--include/npassd/service.h14
-rw-r--r--include/npassd/session.h19
-rw-r--r--meson.build3
-rw-r--r--src/libnpass/meson.build2
-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
11 files changed, 308 insertions, 9 deletions
diff --git a/README.md b/README.md
index 21eef9a..8daca01 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ section.
Todo
====
-- [x] cmdline
+- [x] npass (cli)
- [x] pass init
- [x] pass ls
- [x] pass rm
@@ -18,15 +18,38 @@ Todo
- [x] pass gen
- [x] pass cat
- [x] pass help
-- [ ] dbus
+- [ ] npassd (dbus)
+ - [ ] org.freedesktop.Secret.Service
+ - [x] OpenSession
+ - [ ] CreateCollection
+ - [ ] SearchItems
+ - [ ] Unlock
+ - [ ] Lock
+ - [ ] GetSecrets
+ - [ ] ReadAlias
+ - [ ] SetAlias
+ - [ ] CollectionCreated
+ - [ ] CollectionDeleted
+ - [ ] CollectionChanged
+ - [ ] READ
+ - [x] org.freedesktop.Secret.Session
+ - [x] Close
+ - [ ] org.freedesktop.Secret.Item
+ - [ ] org.freedesktop.Secret.Collection
+ - [ ] org.freedesktop.Secret.Prompt
- [x] nix flake
- [x] shell
- [x] pkg
+ - [ ] module
Dependencies
============
-- meson (*Compile-time)
+- meson (*)
+- pkg-config (*+)
- gpgme
+- basu, elogind or systemd (+)
+
+_\* build-time dependency, + npassd dependency_
Installation
============
diff --git a/flake.nix b/flake.nix
index c3e1b2b..2d53f76 100644
--- a/flake.nix
+++ b/flake.nix
@@ -20,6 +20,9 @@
buildInputs = with pkgs; [
gpgme
+ systemdLibs
+
+ pkg-config
meson
ninja
@@ -39,20 +42,20 @@
};
});
- packages = forAllSystems ({ system, pkgs }: let
- inherit (pkgs) meson ninja gpgme;
- in {
+ packages = forAllSystems ({ system, pkgs }: {
npass = pkgs.stdenv.mkDerivation (finalAttrs: {
pname = "npass";
version = self.shortRev or self.dirtyShortRev;
src = ./.;
- nativeBuildInputs = [
+ nativeBuildInputs = with pkgs; [
meson
ninja
+ pkg-config
];
- buildInputs = [
+ buildInputs = with pkgs; [
gpgme
+ systemdLibs
];
meta = {
diff --git a/include/npassd/common.h b/include/npassd/common.h
new file mode 100644
index 0000000..b3ef866
--- /dev/null
+++ b/include/npassd/common.h
@@ -0,0 +1 @@
+#define DBUS_OBJECT_PATH "/org/freedesktop/secrets"
diff --git a/include/npassd/service.h b/include/npassd/service.h
new file mode 100644
index 0000000..e1a42fc
--- /dev/null
+++ b/include/npassd/service.h
@@ -0,0 +1,14 @@
+#include <systemd/sd-bus.h>
+
+#include "npassd/session.h"
+
+#define MAX_SESSION 128
+
+struct service {
+ sd_bus *bus;
+ sd_bus_slot *slot;
+ struct session session[MAX_SESSION];
+};
+
+int service_init(sd_bus *bus, struct service *service);
+void service_free(struct service *service);
diff --git a/include/npassd/session.h b/include/npassd/session.h
new file mode 100644
index 0000000..6763c6a
--- /dev/null
+++ b/include/npassd/session.h
@@ -0,0 +1,19 @@
+#include <stdbool.h>
+#include <systemd/sd-bus.h>
+
+#include "npassd/common.h"
+
+#define SESSION_IFACE "org.freedesktop.Secret.Session"
+
+/* reusable slots */
+struct session {
+ bool isactive;
+ sd_bus_slot *slot;
+ /* +32 for snprintf("/session/%d") */
+ char path[sizeof(DBUS_OBJECT_PATH) + 32];
+};
+
+void session_init(struct session *s, size_t n);
+int session_slot_available(struct session *s, size_t n);
+int session_free(struct session *s);
+int session_new(sd_bus *bus, struct session *s, unsigned slot_no);
diff --git a/meson.build b/meson.build
index 0384579..b77292e 100644
--- a/meson.build
+++ b/meson.build
@@ -19,7 +19,10 @@ add_project_arguments(
)
gpgme_dep = dependency('gpgme', version: '>= 1.0')
+sdbus_dep = dependency('libsystemd', 'libelogind', 'basu')
+
npass_inc = include_directories('include')
subdir('src/libnpass')
+subdir('src/npassd')
subdir('src/npass')
diff --git a/src/libnpass/meson.build b/src/libnpass/meson.build
index 1ce4621..ac3cd1d 100644
--- a/src/libnpass/meson.build
+++ b/src/libnpass/meson.build
@@ -3,7 +3,7 @@ lib_npass = static_library(
[
'util.c',
'gpg.c',
- 'libnpass.c'
+ 'libnpass.c',
],
dependencies: gpgme_dep,
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;
+}