LCOV - code coverage report
Current view: top level - sbus - sssd_dbus_properties.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 91 0.0 %
Date: 2015-10-19 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Stef Walter <stefw@redhat.com>
       4             :         Pavel Březina <pbrezina@redhat.com>
       5             : 
       6             :     Copyright (C) 2014 Red Hat
       7             : 
       8             :     This program is free software; you can redistribute it and/or modify
       9             :     it under the terms of the GNU General Public License as published by
      10             :     the Free Software Foundation; either version 3 of the License, or
      11             :     (at your option) any later version.
      12             : 
      13             :     This program is distributed in the hope that it will be useful,
      14             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :     GNU General Public License for more details.
      17             : 
      18             :     You should have received a copy of the GNU General Public License
      19             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "config.h"
      23             : 
      24             : #include "util/util.h"
      25             : #include "sbus/sssd_dbus.h"
      26             : #include "sbus/sssd_dbus_meta.h"
      27             : #include "sbus/sssd_dbus_private.h"
      28             : #include "sbus/sssd_dbus_invokers.h"
      29             : 
      30             : #define CHECK_SIGNATURE_OR_FAIL(req, error, label, exp) do { \
      31             :     const char *__sig; \
      32             :     __sig = dbus_message_get_signature(req->message); \
      33             :     if (strcmp(__sig, exp) != 0) { \
      34             :         error = sbus_error_new(req, DBUS_ERROR_INVALID_ARGS, \
      35             :                "Invalid arguments: expected \"%s\", got \"%s\"", exp, __sig); \
      36             :         goto label; \
      37             :     } \
      38             : } while (0)
      39             : 
      40             : struct iface_properties {
      41             :     struct sbus_vtable vtable; /* derive from sbus_vtable */
      42             :     sbus_msg_handler_fn Get;
      43             :     sbus_msg_handler_fn Set;
      44             :     sbus_msg_handler_fn GetAll;
      45             : };
      46             : 
      47             : static int sbus_properties_get(struct sbus_request *sbus_req, void *pvt);
      48             : static int sbus_properties_set(struct sbus_request *sbus_req, void *pvt);
      49             : static int sbus_properties_get_all(struct sbus_request *sbus_req, void *pvt);
      50             : 
      51             : struct sbus_vtable *
      52           0 : sbus_properties_vtable(void)
      53             : {
      54             :     /* Properties.Get */
      55             :     static const struct sbus_arg_meta get_args_in[] = {
      56             :         { "interface_name", "s" },
      57             :         { "property_name", "s" },
      58             :         { NULL, }
      59             :     };
      60             : 
      61             :     static const struct sbus_arg_meta get_args_out[] = {
      62             :         { "value", "v" },
      63             :         { NULL, }
      64             :     };
      65             : 
      66             :     /* Properties.Set */
      67             :     static const struct sbus_arg_meta set_args_in[] = {
      68             :         { "interface_name", "s" },
      69             :         { "property_name", "s" },
      70             :         { "value", "v" },
      71             :         { NULL, }
      72             :     };
      73             : 
      74             :     /* Properties.GetAll */
      75             :     static const struct sbus_arg_meta getall_args_in[] = {
      76             :         { "interface_name", "s" },
      77             :         { NULL, }
      78             :     };
      79             : 
      80             :     static const struct sbus_arg_meta getall_args_out[] = {
      81             :         { "props", "a{sv}" },
      82             :         { NULL, }
      83             :     };
      84             : 
      85             :     static const struct sbus_method_meta iface_methods[] = {
      86             :         {
      87             :             "Get", /* name */
      88             :             get_args_in,
      89             :             get_args_out,
      90             :             offsetof(struct iface_properties, Get),
      91             :             NULL, /* no invoker */
      92             :         },
      93             :         {
      94             :             "Set", /* name */
      95             :             set_args_in,
      96             :             NULL, /* no out_args */
      97             :             offsetof(struct iface_properties, Set),
      98             :             NULL, /* no invoker */
      99             :         },
     100             :         {
     101             :             "GetAll", /* name */
     102             :             getall_args_in,
     103             :             getall_args_out,
     104             :             offsetof(struct iface_properties, GetAll),
     105             :             NULL, /* no invoker */
     106             :         },
     107             :         { NULL, }
     108             :     };
     109             : 
     110             :     static const struct sbus_interface_meta iface_meta = {
     111             :         "org.freedesktop.DBus.Properties", /* name */
     112             :         iface_methods,
     113             :         NULL, /* no signals */
     114             :         NULL, /* no properties */
     115             :         NULL, /* no GetAll invoker */
     116             :     };
     117             : 
     118             :     static struct iface_properties iface = {
     119             :         { &iface_meta, 0 },
     120             :         .Get = sbus_properties_get,
     121             :         .Set = sbus_properties_set,
     122             :         .GetAll = sbus_properties_get_all,
     123             :     };
     124             : 
     125           0 :     return &iface.vtable;
     126             : }
     127             : 
     128             : static struct sbus_request *
     129           0 : sbus_properties_subreq(struct sbus_request *sbus_req,
     130             :                        struct sbus_interface *iface)
     131             : {
     132             :     struct sbus_request *sbus_subreq;
     133             : 
     134             :     /* Create new sbus_request to so it contain given interface. The
     135             :      * old sbus_request talloc context will be attached to this new one
     136             :      * so it is freed together. */
     137           0 :     sbus_subreq = sbus_new_request(sbus_req->conn, iface, sbus_req->message);
     138           0 :     if (sbus_subreq == NULL) {
     139           0 :         return NULL;
     140             :     }
     141             : 
     142           0 :     talloc_steal(sbus_subreq, sbus_req);
     143             : 
     144           0 :     return sbus_subreq;
     145             : }
     146             : 
     147           0 : static int sbus_properties_get(struct sbus_request *sbus_req, void *pvt)
     148             : {
     149             :     DBusError *error;
     150             :     struct sbus_request *sbus_subreq;
     151             :     struct sbus_connection *conn;
     152             :     struct sbus_interface *iface;
     153             :     const struct sbus_property_meta *prop;
     154             :     sbus_msg_handler_fn handler_fn;
     155             :     const char *interface_name;
     156             :     const char *property_name;
     157             :     bool bret;
     158             : 
     159           0 :     conn = talloc_get_type(pvt, struct sbus_connection);
     160             : 
     161           0 :     CHECK_SIGNATURE_OR_FAIL(sbus_req, error, fail, "ss");
     162             : 
     163           0 :     bret = sbus_request_parse_or_finish(sbus_req,
     164             :                                         DBUS_TYPE_STRING, &interface_name,
     165             :                                         DBUS_TYPE_STRING, &property_name,
     166             :                                         DBUS_TYPE_INVALID);
     167           0 :     if (!bret) {
     168             :         /* request was handled */
     169           0 :         return EOK;
     170             :     }
     171             : 
     172             :     /* find interface */
     173           0 :     iface = sbus_opath_hash_lookup_iface(conn->managed_paths, sbus_req->path,
     174             :                                          interface_name);
     175           0 :     if (iface == NULL) {
     176           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_UNKNOWN_INTERFACE,
     177             :                                "Unknown interface");
     178           0 :         goto fail;
     179             :     }
     180             : 
     181             :     /* find property handler */
     182           0 :     prop = sbus_meta_find_property(iface->vtable->meta, property_name);
     183           0 :     if (prop == NULL) {
     184           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_UNKNOWN_PROPERTY,
     185             :                                "Unknown property");
     186           0 :         goto fail;
     187             :     }
     188             : 
     189           0 :     if (!(prop->flags & SBUS_PROPERTY_READABLE)) {
     190           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_ACCESS_DENIED,
     191             :                                "Property is not readable");
     192           0 :         goto fail;
     193             :     }
     194             : 
     195           0 :     handler_fn = VTABLE_FUNC(iface->vtable, prop->vtable_offset_get);
     196           0 :     if (handler_fn == NULL) {
     197           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_NOT_SUPPORTED,
     198             :                                "Getter is not implemented");
     199           0 :         goto fail;
     200             :     }
     201             : 
     202           0 :     sbus_subreq = sbus_properties_subreq(sbus_req, iface);
     203           0 :     if (sbus_subreq == NULL) {
     204           0 :         error = NULL;
     205           0 :         goto fail;
     206             :     }
     207             : 
     208           0 :     sbus_invoke_get(sbus_subreq, prop->type,
     209             :                     prop->invoker_get, handler_fn);
     210           0 :     return EOK;
     211             : 
     212             : fail:
     213           0 :     return sbus_request_fail_and_finish(sbus_req, error);
     214             : }
     215             : 
     216             : /*
     217             :  * We don't implement any handlers for setters yet. This code is for future
     218             :  * use and it is likely it will need some changes.
     219             :  */
     220           0 : static int sbus_properties_set(struct sbus_request *sbus_req, void *pvt)
     221             : {
     222             :     DBusError *error;
     223             :     DBusMessageIter iter;
     224             :     DBusMessageIter iter_variant;
     225             :     struct sbus_request *sbus_subreq;
     226             :     struct sbus_connection *conn;
     227             :     struct sbus_interface *iface;
     228             :     const struct sbus_property_meta *prop;
     229             :     const char *interface_name;
     230             :     const char *property_name;
     231             :     const char *variant_sig;
     232             :     sbus_msg_handler_fn handler_fn;
     233             : 
     234           0 :     conn = talloc_get_type(pvt, struct sbus_connection);
     235             : 
     236           0 :     CHECK_SIGNATURE_OR_FAIL(sbus_req, error, fail, "ssv");
     237             : 
     238             :     /* get interface and property */
     239           0 :     dbus_message_iter_init(sbus_req->message, &iter);
     240           0 :     dbus_message_iter_get_basic(&iter, &interface_name);
     241           0 :     dbus_message_iter_next(&iter);
     242           0 :     dbus_message_iter_get_basic(&iter, &property_name);
     243           0 :     dbus_message_iter_next(&iter);
     244             : 
     245             :     /* find interface */
     246           0 :     iface = sbus_opath_hash_lookup_iface(conn->managed_paths, sbus_req->path,
     247             :                                          interface_name);
     248           0 :     if (iface == NULL) {
     249           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_UNKNOWN_INTERFACE,
     250             :                                "Unknown interface");
     251           0 :         goto fail;
     252             :     }
     253             : 
     254             :     /* find property handler */
     255           0 :     prop = sbus_meta_find_property(iface->vtable->meta, property_name);
     256           0 :     if (prop == NULL) {
     257           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_UNKNOWN_PROPERTY,
     258             :                                "Unknown property");
     259           0 :         goto fail;
     260             :     }
     261             : 
     262           0 :     if (!(prop->flags & SBUS_PROPERTY_WRITABLE)) {
     263           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_ACCESS_DENIED,
     264             :                                "Property is not writable");
     265           0 :         goto fail;
     266             :     }
     267             : 
     268           0 :     handler_fn = VTABLE_FUNC(iface->vtable, prop->vtable_offset_set);
     269           0 :     if (handler_fn == NULL) {
     270           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_NOT_SUPPORTED,
     271             :                                "Setter is not implemented");
     272           0 :         goto fail;
     273             :     }
     274             : 
     275             :     /* check variant type */
     276           0 :     dbus_message_iter_recurse(&iter, &iter_variant);
     277           0 :     variant_sig = dbus_message_iter_get_signature(&iter_variant);
     278           0 :     if (strcmp(prop->type, variant_sig) != 0) {
     279           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_INVALID_ARGS,
     280             :                                "Invalid data type for property");
     281           0 :         goto fail;
     282             :     }
     283             : 
     284           0 :     sbus_subreq = sbus_properties_subreq(sbus_req, iface);
     285           0 :     if (sbus_subreq == NULL) {
     286           0 :         error = NULL;
     287           0 :         goto fail;
     288             :     }
     289             : 
     290           0 :     sbus_request_invoke_or_finish(sbus_subreq, handler_fn,
     291             :                                   iface->handler_data, prop->invoker_set);
     292             : 
     293           0 :     return EOK;
     294             : 
     295             : fail:
     296           0 :     return sbus_request_fail_and_finish(sbus_req, error);
     297             : }
     298             : 
     299           0 : static int sbus_properties_get_all(struct sbus_request *sbus_req, void *pvt)
     300             : {
     301             :     DBusError *error;
     302             :     struct sbus_request *sbus_subreq;
     303             :     struct sbus_connection *conn;
     304             :     struct sbus_interface *iface;
     305             :     const char *interface_name;
     306             :     bool bret;
     307             : 
     308           0 :     conn = talloc_get_type(pvt, struct sbus_connection);
     309             : 
     310           0 :     CHECK_SIGNATURE_OR_FAIL(sbus_req, error, fail, "s");
     311             : 
     312           0 :     bret = sbus_request_parse_or_finish(sbus_req,
     313             :                                         DBUS_TYPE_STRING, &interface_name,
     314             :                                         DBUS_TYPE_INVALID);
     315           0 :     if (!bret) {
     316             :         /* request was handled */
     317           0 :         return EOK;
     318             :     }
     319             : 
     320             :     /* find interface */
     321           0 :     iface = sbus_opath_hash_lookup_iface(conn->managed_paths, sbus_req->path,
     322             :                                          interface_name);
     323           0 :     if (iface == NULL) {
     324           0 :         error = sbus_error_new(sbus_req, DBUS_ERROR_UNKNOWN_INTERFACE,
     325             :                                "Unknown interface");
     326           0 :         goto fail;
     327             :     }
     328             : 
     329           0 :     sbus_subreq = sbus_properties_subreq(sbus_req, iface);
     330           0 :     if (sbus_subreq == NULL) {
     331           0 :         error = NULL;
     332           0 :         goto fail;
     333             :     }
     334             : 
     335           0 :     if (iface->vtable->meta->invoker_get_all == NULL) {
     336           0 :         DEBUG(SSSDBG_TRACE_FUNC, "No get all invoker set,"
     337             :               "using the default one\n");
     338             : 
     339           0 :         sbus_invoke_get_all(sbus_req);
     340             :     } else {
     341           0 :         iface->vtable->meta->invoker_get_all(sbus_subreq);
     342             :     }
     343             : 
     344           0 :     return EOK;
     345             : 
     346             : fail:
     347           0 :     return sbus_request_fail_and_finish(sbus_req, error);
     348             : }

Generated by: LCOV version 1.10