#include #include #include #include #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 int handle_search_items(sd_bus_message *msg, void *data, sd_bus_error *ret_error); static int handle_create_collection(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_METHOD("SearchItems", "a{ss}", "aoao", handle_search_items, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateCollection", "a{sv}s", "oo", handle_create_collection, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, }; static int handle_search_items(__attribute__((unused)) sd_bus_message *msg, __attribute__((unused)) void *data, __attribute__((unused)) sd_bus_error *ret_error) { return sd_bus_reply_method_return(msg, "aoao", 0, 0); } static int handle_create_collection(sd_bus_message *msg, void *data, __attribute__((unused)) sd_bus_error *ret_error) { const char *label, *alias, *key; struct service *service = data; struct collection *collection; char *root; int ret; ret = sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY, "{sv}"); if (ret <= 0) { print_err("%s", strerror(ret < 0 ? -ret : EINVAL)); return ret < 0 ? ret : -EINVAL; } ret = sd_bus_message_enter_container(msg, SD_BUS_TYPE_DICT_ENTRY, "sv"); if (ret <= 0) { print_err("%s", strerror(ret < 0 ? -ret : EINVAL)); return ret < 0 ? ret : -EINVAL; } ret = sd_bus_message_read(msg, "s", &key); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } ret = strcmp("org.freedesktop.Secret.Collection.Label", key); if (ret) { print_err("Unsupported property key: %s", key); return -EINVAL; } ret = sd_bus_message_read(msg, "v", "s", &label); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } ret = sd_bus_message_exit_container(msg); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } ret = sd_bus_message_exit_container(msg); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } ret = sd_bus_message_read(msg, "s", &alias); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } ret = collection_root_make(label, alias, &root); if (ret < 0) return ret; ret = collection_new(service->bus, service->db, &collection, alias, label, root); free(root); if (ret < 0) return ret; ret = sd_bus_reply_method_return(msg, "oo", collection->path, "/"); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } LIST_INSERT_HEAD(&service->collections, collection, dlist); return ret; } static int handle_open_session(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { struct service *service = data; struct session *session; const char *sender; char *algo; int ret; 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; } sender = sd_bus_message_get_sender(msg); ret = session_new(service->bus, &session, sender); if (ret < 0) return ret; ret = sd_bus_reply_method_return(msg, "vo", "s", NULL, session->path); if (ret < 0) { print_err("%s", strerror(-ret)); return ret; } LIST_INSERT_HEAD(&service->sessions, session, dlist); return ret; } void service_free(struct service *service) { struct session *s; struct collection *c; LIST_FOREACH (s, &service->sessions, dlist) session_free(s); LIST_FOREACH (c, &service->collections, dlist) collection_free(c); sd_bus_slot_unref(service->slot); } int service_init(sd_bus *bus, struct service *service) { int ret; service->bus = bus; LIST_INIT(&service->sessions); LIST_INIT(&service->collections); 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; }