From 6f0fb6644fbb9fe2c05f1719e619ce4d0073728d Mon Sep 17 00:00:00 2001 From: sinanmohd Date: Sun, 21 Apr 2024 15:30:07 +0530 Subject: npassd/session: free session when owner service disconnects from the bus --- include/npassd/session.h | 5 +++- src/npassd/service.c | 4 ++- src/npassd/session.c | 64 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/include/npassd/session.h b/include/npassd/session.h index 6763c6a..a3aa705 100644 --- a/include/npassd/session.h +++ b/include/npassd/session.h @@ -4,11 +4,13 @@ #include "npassd/common.h" #define SESSION_IFACE "org.freedesktop.Secret.Session" +#define MAX_OWNER_LEN 64 /* reusable slots */ struct session { bool isactive; sd_bus_slot *slot; + char owner[MAX_OWNER_LEN]; /* +32 for snprintf("/session/%d") */ char path[sizeof(DBUS_OBJECT_PATH) + 32]; }; @@ -16,4 +18,5 @@ struct session { 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); +int session_new(sd_bus *bus, struct session *session, unsigned session_no, + const char *owner); diff --git a/src/npassd/service.c b/src/npassd/service.c index 60e458b..c93073a 100644 --- a/src/npassd/service.c +++ b/src/npassd/service.c @@ -23,6 +23,7 @@ static int handle_open_session(sd_bus_message *msg, void *data, { struct service *service = data; int ret, session_slot_no; + const char *sender; char *algo; ret = sd_bus_message_read(msg, "s", &algo); @@ -43,8 +44,9 @@ static int handle_open_session(sd_bus_message *msg, void *data, return ret; } + sender = sd_bus_message_get_sender(msg); ret = session_new(service->bus, &service->session[session_slot_no], - session_slot_no); + session_slot_no, sender); if (ret < 0) return ret; diff --git a/src/npassd/session.c b/src/npassd/session.c index e674bb7..7190aec 100644 --- a/src/npassd/session.c +++ b/src/npassd/session.c @@ -11,6 +11,9 @@ static int handle_close(__attribute__((unused)) sd_bus_message *msg, void *data, __attribute__((unused)) sd_bus_error *ret_error); +static int handle_nameownerchanged(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), @@ -19,6 +22,28 @@ static const sd_bus_vtable session_vtable[] = { SD_BUS_VTABLE_END, }; +static int handle_nameownerchanged(sd_bus_message *msg, void *data, + __attribute__((unused)) + sd_bus_error *ret_error) +{ + struct session *session = data; + const char *name; + int ret; + + ret = sd_bus_message_read(msg, "ss", NULL, &name); + if (ret < 0) { + print_err("%s", strerror(-ret)); + return ret; + } + + ret = strcmp(session->owner, name); + if (ret) + return 0; + + session_free(session); + return 0; +} + static int handle_close(__attribute__((unused)) sd_bus_message *msg, void *data, __attribute__((unused)) sd_bus_error *ret_error) { @@ -28,7 +53,7 @@ static int handle_close(__attribute__((unused)) sd_bus_message *msg, void *data, if (ret < 0) print_err("Failed to free session: %s", strerror(-ret)); - return ret; + return sd_bus_reply_method_return(msg, ""); } int session_slot_available(struct session *s, size_t n) @@ -47,25 +72,48 @@ int session_slot_available(struct session *s, size_t n) return -ENOMEM; } -int session_new(sd_bus *bus, struct session *session, unsigned session_no) +int session_new(sd_bus *bus, struct session *session, unsigned session_no, + const char *owner) { int ret; - snprintf(session->path, sizeof(session->path), - DBUS_OBJECT_PATH "/session/%d", session_no); + ret = snprintf(session->path, sizeof(session->path), + DBUS_OBJECT_PATH "/session/%d", session_no); + if (ret < 0 || (size_t)ret > sizeof(session->path)) { + print_err("%s", "Failed to create session path"); + return -ENOMEM; + } + + ret = snprintf(session->owner, sizeof(session->owner), "%s", owner); + if (ret < 0 || (size_t)ret > sizeof(session->owner)) { + print_err("%s", "Failed to set session owner"); + return -ENOMEM; + } + ret = sd_bus_add_object_vtable(bus, &session->slot, session->path, SESSION_IFACE, session_vtable, session); - if (ret < 0) + if (ret < 0) { print_err("Failed to create session: %s", strerror(-ret)); - else - session->isactive = true; + return ret; + } + session->isactive = true; + + ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", "NameOwnerChanged", + handle_nameownerchanged, session); + if (ret < 0) { + session_free(session); + print_err("%s", strerror(-ret)); + return ret; + } return ret; } int session_free(struct session *s) { - if (!s->isactive) + if (s->isactive == false) return -EINVAL; s->isactive = false; -- cgit v1.2.3