sssd_dbus_interface.c revision d87e960c17d7598781cf032d06ba03a3ecadbfa2
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina/*
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina Authors:
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina Pavel Březina <pbrezina@redhat.com>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina Copyright (C) 2014 Red Hat
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina This program is free software; you can redistribute it and/or modify
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina it under the terms of the GNU General Public License as published by
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina the Free Software Foundation; either version 3 of the License, or
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (at your option) any later version.
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina This program is distributed in the hope that it will be useful,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina GNU General Public License for more details.
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina You should have received a copy of the GNU General Public License
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina*/
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <talloc.h>
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina#include <dbus/dbus.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina#include "util/util.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "sbus/sssd_dbus.h"
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina#include "sbus/sssd_dbus_private.h"
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel BřezinaDBusObjectPathVTable dbus_object_path_vtable =
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina { NULL, sbus_message_handler, NULL, NULL, NULL, NULL };
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic char *sbus_iface_get_reg_path(TALLOC_CTX *mem_ctx,
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina const char *path,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina bool fallback)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina{
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina char *reg_path;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina reg_path = talloc_strdup(mem_ctx, path);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (reg_path == NULL) return NULL;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (fallback) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina reg_path[strlen(path)-1] = '\0';
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina }
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina return reg_path;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina}
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic bool path_in_interface_list(struct sbus_interface_p *list,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char *path)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct sbus_interface_p *iter;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (!list || !path) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return false;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina iter = list;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina while (iter != NULL) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (strcmp(iter->intf->path, path) == 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return true;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina iter = iter->next;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return false;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavoid sbus_unreg_object_paths(struct sbus_connection *conn)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct sbus_interface_p *iter = conn->intf_list;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina while (iter != NULL) {
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik dbus_connection_unregister_object_path(conn->dbus.conn,
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik iter->intf->path);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina iter = iter->next;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic bool sbus_fb_path_has_prefix(const char *path, const char *prefix)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* strlen-1 because we don't want to match the trailing '*' */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (strncmp(path, prefix, strlen(prefix)-1) == 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return true;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return false;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic bool sbus_path_has_fallback(const char *path)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek char *wildcard;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek wildcard = strrchr(path, '*');
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (wildcard != NULL) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* This path was registered as fallback */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (*(wildcard + 1) != '\0') {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* Wildcard is only allowed as the last character in the path */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return false;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return true;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return false;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekbool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *path)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (sbus_path_has_fallback(intf_p->intf->path)) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return sbus_fb_path_has_prefix(path, intf_p->intf->path);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return strcmp(path, intf_p->intf->path) == 0;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic struct sbus_interface *
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinasbus_new_interface(TALLOC_CTX *mem_ctx,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *object_path,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct sbus_vtable *iface_vtable,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina void *instance_data)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct sbus_interface *intf;
11a87c5f091d6c092b5dadd3d67f900213e280daPetr Cech
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf = talloc_zero(mem_ctx, struct sbus_interface);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (intf == NULL) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Cannot allocate a new sbus_interface.\n");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf->path = talloc_strdup(intf, object_path);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (intf->path == NULL) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Cannot duplicate object path.\n");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina talloc_free(intf);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf->vtable = iface_vtable;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf->instance_data = instance_data;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return intf;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinaint sbus_conn_register_iface(struct sbus_connection *conn,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct sbus_vtable *iface_vtable,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *object_path,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina void *pvt)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct sbus_interface_p *intf_p;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct sbus_interface *intf;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina dbus_bool_t dbret;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *path;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina bool fallback;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf = sbus_new_interface(conn, object_path, iface_vtable, pvt);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (intf == NULL) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return ENOMEM;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (!conn || !intf->vtable || !intf->vtable->meta) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return EINVAL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina path = intf->path;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina fallback = sbus_path_has_fallback(path);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (path_in_interface_list(conn->intf_list, path)) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "Cannot add method context with identical path.\n");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return EINVAL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p = talloc_zero(conn, struct sbus_interface_p);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (!intf_p) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return ENOMEM;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->conn = conn;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->intf = intf;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->reg_path = sbus_iface_get_reg_path(intf_p, path, fallback);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (intf_p->reg_path == NULL) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return ENOMEM;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DLIST_ADD(conn->intf_list, intf_p);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DEBUG(SSSDBG_TRACE_LIBS, "Will register path %s with%s fallback\n",
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->reg_path, fallback ? "" : "out");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (fallback) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina dbret = dbus_connection_register_fallback(conn->dbus.conn,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->reg_path,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina &dbus_object_path_vtable,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina } else {
11a87c5f091d6c092b5dadd3d67f900213e280daPetr Cech dbret = dbus_connection_register_object_path(conn->dbus.conn,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p->reg_path,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina &dbus_object_path_vtable,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina intf_p);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (!dbret) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "Could not register object path to the connection.\n");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return ENOMEM;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return EOK;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina