LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-convenience.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 162 329 49.2 %
Date: 2019-08-22 15:41:25 Functions: 11 17 64.7 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <unistd.h>
       4             : #include <sys/types.h>
       5             : 
       6             : #include "bus-internal.h"
       7             : #include "bus-message.h"
       8             : #include "bus-signature.h"
       9             : #include "bus-type.h"
      10             : #include "bus-util.h"
      11             : #include "string-util.h"
      12             : 
      13           0 : _public_ int sd_bus_emit_signal(
      14             :                 sd_bus *bus,
      15             :                 const char *path,
      16             :                 const char *interface,
      17             :                 const char *member,
      18             :                 const char *types, ...) {
      19             : 
      20           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
      21             :         int r;
      22             : 
      23           0 :         assert_return(bus, -EINVAL);
      24           0 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
      25           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      26             : 
      27           0 :         if (!BUS_IS_OPEN(bus->state))
      28           0 :                 return -ENOTCONN;
      29             : 
      30           0 :         r = sd_bus_message_new_signal(bus, &m, path, interface, member);
      31           0 :         if (r < 0)
      32           0 :                 return r;
      33             : 
      34           0 :         if (!isempty(types)) {
      35             :                 va_list ap;
      36             : 
      37           0 :                 va_start(ap, types);
      38           0 :                 r = sd_bus_message_appendv(m, types, ap);
      39           0 :                 va_end(ap);
      40           0 :                 if (r < 0)
      41           0 :                         return r;
      42             :         }
      43             : 
      44           0 :         return sd_bus_send(bus, m, NULL);
      45             : }
      46             : 
      47          34 : _public_ int sd_bus_call_method_async(
      48             :                 sd_bus *bus,
      49             :                 sd_bus_slot **slot,
      50             :                 const char *destination,
      51             :                 const char *path,
      52             :                 const char *interface,
      53             :                 const char *member,
      54             :                 sd_bus_message_handler_t callback,
      55             :                 void *userdata,
      56             :                 const char *types, ...) {
      57             : 
      58          34 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
      59             :         int r;
      60             : 
      61          34 :         assert_return(bus, -EINVAL);
      62          34 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
      63          34 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      64             : 
      65          34 :         if (!BUS_IS_OPEN(bus->state))
      66          16 :                 return -ENOTCONN;
      67             : 
      68          18 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
      69          18 :         if (r < 0)
      70           0 :                 return r;
      71             : 
      72          18 :         if (!isempty(types)) {
      73             :                 va_list ap;
      74             : 
      75          17 :                 va_start(ap, types);
      76          17 :                 r = sd_bus_message_appendv(m, types, ap);
      77          17 :                 va_end(ap);
      78          17 :                 if (r < 0)
      79           0 :                         return r;
      80             :         }
      81             : 
      82          18 :         return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
      83             : }
      84             : 
      85          31 : _public_ int sd_bus_call_method(
      86             :                 sd_bus *bus,
      87             :                 const char *destination,
      88             :                 const char *path,
      89             :                 const char *interface,
      90             :                 const char *member,
      91             :                 sd_bus_error *error,
      92             :                 sd_bus_message **reply,
      93             :                 const char *types, ...) {
      94             : 
      95          31 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
      96             :         int r;
      97             : 
      98          31 :         bus_assert_return(bus, -EINVAL, error);
      99          31 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     100             : 
     101          31 :         if (!BUS_IS_OPEN(bus->state)) {
     102           0 :                 r = -ENOTCONN;
     103           0 :                 goto fail;
     104             :         }
     105             : 
     106          31 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
     107          31 :         if (r < 0)
     108           0 :                 goto fail;
     109             : 
     110          31 :         if (!isempty(types)) {
     111             :                 va_list ap;
     112             : 
     113          14 :                 va_start(ap, types);
     114          14 :                 r = sd_bus_message_appendv(m, types, ap);
     115          14 :                 va_end(ap);
     116          14 :                 if (r < 0)
     117           0 :                         goto fail;
     118             :         }
     119             : 
     120          31 :         return sd_bus_call(bus, m, 0, error, reply);
     121             : 
     122           0 : fail:
     123           0 :         return sd_bus_error_set_errno(error, r);
     124             : }
     125             : 
     126          20 : _public_ int sd_bus_reply_method_return(
     127             :                 sd_bus_message *call,
     128             :                 const char *types, ...) {
     129             : 
     130          20 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     131             :         int r;
     132             : 
     133          20 :         assert_return(call, -EINVAL);
     134          20 :         assert_return(call->sealed, -EPERM);
     135          20 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     136          20 :         assert_return(call->bus, -EINVAL);
     137          20 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     138             : 
     139          20 :         if (!BUS_IS_OPEN(call->bus->state))
     140           0 :                 return -ENOTCONN;
     141             : 
     142          20 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     143           3 :                 return 0;
     144             : 
     145          17 :         r = sd_bus_message_new_method_return(call, &m);
     146          17 :         if (r < 0)
     147           0 :                 return r;
     148             : 
     149          17 :         if (!isempty(types)) {
     150             :                 va_list ap;
     151             : 
     152           3 :                 va_start(ap, types);
     153           3 :                 r = sd_bus_message_appendv(m, types, ap);
     154           3 :                 va_end(ap);
     155           3 :                 if (r < 0)
     156           0 :                         return r;
     157             :         }
     158             : 
     159          17 :         return sd_bus_send(call->bus, m, NULL);
     160             : }
     161             : 
     162           4 : _public_ int sd_bus_reply_method_error(
     163             :                 sd_bus_message *call,
     164             :                 const sd_bus_error *e) {
     165             : 
     166           4 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     167             :         int r;
     168             : 
     169           4 :         assert_return(call, -EINVAL);
     170           4 :         assert_return(call->sealed, -EPERM);
     171           4 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     172           4 :         assert_return(sd_bus_error_is_set(e), -EINVAL);
     173           4 :         assert_return(call->bus, -EINVAL);
     174           4 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     175             : 
     176           4 :         if (!BUS_IS_OPEN(call->bus->state))
     177           0 :                 return -ENOTCONN;
     178             : 
     179           4 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     180           0 :                 return 0;
     181             : 
     182           4 :         r = sd_bus_message_new_method_error(call, &m, e);
     183           4 :         if (r < 0)
     184           0 :                 return r;
     185             : 
     186           4 :         return sd_bus_send(call->bus, m, NULL);
     187             : }
     188             : 
     189           4 : _public_ int sd_bus_reply_method_errorf(
     190             :                 sd_bus_message *call,
     191             :                 const char *name,
     192             :                 const char *format,
     193             :                 ...) {
     194             : 
     195           4 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     196             :         va_list ap;
     197             : 
     198           4 :         assert_return(call, -EINVAL);
     199           4 :         assert_return(call->sealed, -EPERM);
     200           4 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     201           4 :         assert_return(call->bus, -EINVAL);
     202           4 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     203             : 
     204           4 :         if (!BUS_IS_OPEN(call->bus->state))
     205           0 :                 return -ENOTCONN;
     206             : 
     207           4 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     208           0 :                 return 0;
     209             : 
     210           4 :         va_start(ap, format);
     211           4 :         bus_error_setfv(&error, name, format, ap);
     212           4 :         va_end(ap);
     213             : 
     214           4 :         return sd_bus_reply_method_error(call, &error);
     215             : }
     216             : 
     217           0 : _public_ int sd_bus_reply_method_errno(
     218             :                 sd_bus_message *call,
     219             :                 int error,
     220             :                 const sd_bus_error *p) {
     221             : 
     222           0 :         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
     223             : 
     224           0 :         assert_return(call, -EINVAL);
     225           0 :         assert_return(call->sealed, -EPERM);
     226           0 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     227           0 :         assert_return(call->bus, -EINVAL);
     228           0 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     229             : 
     230           0 :         if (!BUS_IS_OPEN(call->bus->state))
     231           0 :                 return -ENOTCONN;
     232             : 
     233           0 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     234           0 :                 return 0;
     235             : 
     236           0 :         if (sd_bus_error_is_set(p))
     237           0 :                 return sd_bus_reply_method_error(call, p);
     238             : 
     239           0 :         sd_bus_error_set_errno(&berror, error);
     240             : 
     241           0 :         return sd_bus_reply_method_error(call, &berror);
     242             : }
     243             : 
     244           0 : _public_ int sd_bus_reply_method_errnof(
     245             :                 sd_bus_message *call,
     246             :                 int error,
     247             :                 const char *format,
     248             :                 ...) {
     249             : 
     250           0 :         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
     251             :         va_list ap;
     252             : 
     253           0 :         assert_return(call, -EINVAL);
     254           0 :         assert_return(call->sealed, -EPERM);
     255           0 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     256           0 :         assert_return(call->bus, -EINVAL);
     257           0 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     258             : 
     259           0 :         if (!BUS_IS_OPEN(call->bus->state))
     260           0 :                 return -ENOTCONN;
     261             : 
     262           0 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     263           0 :                 return 0;
     264             : 
     265           0 :         va_start(ap, format);
     266           0 :         sd_bus_error_set_errnofv(&berror, error, format, ap);
     267           0 :         va_end(ap);
     268             : 
     269           0 :         return sd_bus_reply_method_error(call, &berror);
     270             : }
     271             : 
     272           3 : _public_ int sd_bus_get_property(
     273             :                 sd_bus *bus,
     274             :                 const char *destination,
     275             :                 const char *path,
     276             :                 const char *interface,
     277             :                 const char *member,
     278             :                 sd_bus_error *error,
     279             :                 sd_bus_message **reply,
     280             :                 const char *type) {
     281             : 
     282           3 :         sd_bus_message *rep = NULL;
     283             :         int r;
     284             : 
     285           3 :         bus_assert_return(bus, -EINVAL, error);
     286           3 :         bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
     287           3 :         bus_assert_return(member_name_is_valid(member), -EINVAL, error);
     288           3 :         bus_assert_return(reply, -EINVAL, error);
     289           3 :         bus_assert_return(signature_is_single(type, false), -EINVAL, error);
     290           3 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     291             : 
     292           3 :         if (!BUS_IS_OPEN(bus->state)) {
     293           0 :                 r = -ENOTCONN;
     294           0 :                 goto fail;
     295             :         }
     296             : 
     297           3 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
     298           3 :         if (r < 0)
     299           0 :                 return r;
     300             : 
     301           3 :         r = sd_bus_message_enter_container(rep, 'v', type);
     302           3 :         if (r < 0) {
     303           0 :                 sd_bus_message_unref(rep);
     304           0 :                 goto fail;
     305             :         }
     306             : 
     307           3 :         *reply = rep;
     308           3 :         return 0;
     309             : 
     310           0 : fail:
     311           0 :         return sd_bus_error_set_errno(error, r);
     312             : }
     313             : 
     314           0 : _public_ int sd_bus_get_property_trivial(
     315             :                 sd_bus *bus,
     316             :                 const char *destination,
     317             :                 const char *path,
     318             :                 const char *interface,
     319             :                 const char *member,
     320             :                 sd_bus_error *error,
     321             :                 char type, void *ptr) {
     322             : 
     323           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     324             :         int r;
     325             : 
     326           0 :         bus_assert_return(bus, -EINVAL, error);
     327           0 :         bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
     328           0 :         bus_assert_return(member_name_is_valid(member), -EINVAL, error);
     329           0 :         bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
     330           0 :         bus_assert_return(ptr, -EINVAL, error);
     331           0 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     332             : 
     333           0 :         if (!BUS_IS_OPEN(bus->state)) {
     334           0 :                 r = -ENOTCONN;
     335           0 :                 goto fail;
     336             :         }
     337             : 
     338           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     339           0 :         if (r < 0)
     340           0 :                 return r;
     341             : 
     342           0 :         r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
     343           0 :         if (r < 0)
     344           0 :                 goto fail;
     345             : 
     346           0 :         r = sd_bus_message_read_basic(reply, type, ptr);
     347           0 :         if (r < 0)
     348           0 :                 goto fail;
     349             : 
     350           0 :         return 0;
     351             : 
     352           0 : fail:
     353           0 :         return sd_bus_error_set_errno(error, r);
     354             : }
     355             : 
     356           0 : _public_ int sd_bus_get_property_string(
     357             :                 sd_bus *bus,
     358             :                 const char *destination,
     359             :                 const char *path,
     360             :                 const char *interface,
     361             :                 const char *member,
     362             :                 sd_bus_error *error,
     363             :                 char **ret) {
     364             : 
     365           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     366             :         const char *s;
     367             :         char *n;
     368             :         int r;
     369             : 
     370           0 :         bus_assert_return(bus, -EINVAL, error);
     371           0 :         bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
     372           0 :         bus_assert_return(member_name_is_valid(member), -EINVAL, error);
     373           0 :         bus_assert_return(ret, -EINVAL, error);
     374           0 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     375             : 
     376           0 :         if (!BUS_IS_OPEN(bus->state)) {
     377           0 :                 r = -ENOTCONN;
     378           0 :                 goto fail;
     379             :         }
     380             : 
     381           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     382           0 :         if (r < 0)
     383           0 :                 return r;
     384             : 
     385           0 :         r = sd_bus_message_enter_container(reply, 'v', "s");
     386           0 :         if (r < 0)
     387           0 :                 goto fail;
     388             : 
     389           0 :         r = sd_bus_message_read_basic(reply, 's', &s);
     390           0 :         if (r < 0)
     391           0 :                 goto fail;
     392             : 
     393           0 :         n = strdup(s);
     394           0 :         if (!n) {
     395           0 :                 r = -ENOMEM;
     396           0 :                 goto fail;
     397             :         }
     398             : 
     399           0 :         *ret = n;
     400           0 :         return 0;
     401             : 
     402           0 : fail:
     403           0 :         return sd_bus_error_set_errno(error, r);
     404             : }
     405             : 
     406           0 : _public_ int sd_bus_get_property_strv(
     407             :                 sd_bus *bus,
     408             :                 const char *destination,
     409             :                 const char *path,
     410             :                 const char *interface,
     411             :                 const char *member,
     412             :                 sd_bus_error *error,
     413             :                 char ***ret) {
     414             : 
     415           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     416             :         int r;
     417             : 
     418           0 :         bus_assert_return(bus, -EINVAL, error);
     419           0 :         bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
     420           0 :         bus_assert_return(member_name_is_valid(member), -EINVAL, error);
     421           0 :         bus_assert_return(ret, -EINVAL, error);
     422           0 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     423             : 
     424           0 :         if (!BUS_IS_OPEN(bus->state)) {
     425           0 :                 r = -ENOTCONN;
     426           0 :                 goto fail;
     427             :         }
     428             : 
     429           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     430           0 :         if (r < 0)
     431           0 :                 return r;
     432             : 
     433           0 :         r = sd_bus_message_enter_container(reply, 'v', NULL);
     434           0 :         if (r < 0)
     435           0 :                 goto fail;
     436             : 
     437           0 :         r = sd_bus_message_read_strv(reply, ret);
     438           0 :         if (r < 0)
     439           0 :                 goto fail;
     440             : 
     441           0 :         return 0;
     442             : 
     443           0 : fail:
     444           0 :         return sd_bus_error_set_errno(error, r);
     445             : }
     446             : 
     447           3 : _public_ int sd_bus_set_property(
     448             :                 sd_bus *bus,
     449             :                 const char *destination,
     450             :                 const char *path,
     451             :                 const char *interface,
     452             :                 const char *member,
     453             :                 sd_bus_error *error,
     454             :                 const char *type, ...) {
     455             : 
     456           3 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     457             :         va_list ap;
     458             :         int r;
     459             : 
     460           3 :         bus_assert_return(bus, -EINVAL, error);
     461           3 :         bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
     462           3 :         bus_assert_return(member_name_is_valid(member), -EINVAL, error);
     463           3 :         bus_assert_return(signature_is_single(type, false), -EINVAL, error);
     464           3 :         bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
     465             : 
     466           3 :         if (!BUS_IS_OPEN(bus->state)) {
     467           0 :                 r = -ENOTCONN;
     468           0 :                 goto fail;
     469             :         }
     470             : 
     471           3 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
     472           3 :         if (r < 0)
     473           0 :                 goto fail;
     474             : 
     475           3 :         r = sd_bus_message_append(m, "ss", strempty(interface), member);
     476           3 :         if (r < 0)
     477           0 :                 goto fail;
     478             : 
     479           3 :         r = sd_bus_message_open_container(m, 'v', type);
     480           3 :         if (r < 0)
     481           0 :                 goto fail;
     482             : 
     483           3 :         va_start(ap, type);
     484           3 :         r = sd_bus_message_appendv(m, type, ap);
     485           3 :         va_end(ap);
     486           3 :         if (r < 0)
     487           0 :                 goto fail;
     488             : 
     489           3 :         r = sd_bus_message_close_container(m);
     490           3 :         if (r < 0)
     491           0 :                 goto fail;
     492             : 
     493           3 :         return sd_bus_call(bus, m, 0, error, NULL);
     494             : 
     495           0 : fail:
     496           0 :         return sd_bus_error_set_errno(error, r);
     497             : }
     498             : 
     499          13 : _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
     500             :         sd_bus_creds *c;
     501             : 
     502          13 :         assert_return(call, -EINVAL);
     503          13 :         assert_return(call->sealed, -EPERM);
     504          13 :         assert_return(call->bus, -EINVAL);
     505          13 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     506             : 
     507          13 :         if (!BUS_IS_OPEN(call->bus->state))
     508           0 :                 return -ENOTCONN;
     509             : 
     510          13 :         c = sd_bus_message_get_creds(call);
     511             : 
     512             :         /* All data we need? */
     513          13 :         if (c && (mask & ~c->mask) == 0) {
     514           0 :                 *creds = sd_bus_creds_ref(c);
     515           0 :                 return 0;
     516             :         }
     517             : 
     518             :         /* No data passed? Or not enough data passed to retrieve the missing bits? */
     519          13 :         if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
     520             :                 /* We couldn't read anything from the call, let's try
     521             :                  * to get it from the sender or peer. */
     522             : 
     523          13 :                 if (call->sender)
     524             :                         /* There's a sender, but the creds are missing. */
     525           0 :                         return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
     526             :                 else
     527             :                         /* There's no sender. For direct connections
     528             :                          * the credentials of the AF_UNIX peer matter,
     529             :                          * which may be queried via sd_bus_get_owner_creds(). */
     530          13 :                         return sd_bus_get_owner_creds(call->bus, mask, creds);
     531             :         }
     532             : 
     533           0 :         return bus_creds_extend_by_pid(c, mask, creds);
     534             : }
     535             : 
     536          13 : _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
     537          13 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     538             :         uid_t our_uid;
     539          13 :         bool know_caps = false;
     540             :         int r;
     541             : 
     542          13 :         assert_return(call, -EINVAL);
     543          13 :         assert_return(call->sealed, -EPERM);
     544          13 :         assert_return(call->bus, -EINVAL);
     545          13 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     546             : 
     547          13 :         if (!BUS_IS_OPEN(call->bus->state))
     548           0 :                 return -ENOTCONN;
     549             : 
     550          13 :         if (capability >= 0) {
     551             : 
     552          13 :                 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
     553          13 :                 if (r < 0)
     554           0 :                         return r;
     555             : 
     556             :                 /* We cannot use augmented caps for authorization,
     557             :                  * since then data is acquired raceful from
     558             :                  * /proc. This can never actually happen, but let's
     559             :                  * better be safe than sorry, and do an extra check
     560             :                  * here. */
     561          13 :                 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
     562             : 
     563          13 :                 r = sd_bus_creds_has_effective_cap(creds, capability);
     564          13 :                 if (r > 0)
     565           0 :                         return 1;
     566          13 :                 if (r == 0)
     567           0 :                         know_caps = true;
     568             :         } else {
     569           0 :                 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
     570           0 :                 if (r < 0)
     571           0 :                         return r;
     572             :         }
     573             : 
     574             :         /* Now, check the UID, but only if the capability check wasn't
     575             :          * sufficient */
     576          13 :         our_uid = getuid();
     577          13 :         if (our_uid != 0 || !know_caps || capability < 0) {
     578             :                 uid_t sender_uid;
     579             : 
     580             :                 /* We cannot use augmented uid/euid for authorization,
     581             :                  * since then data is acquired raceful from
     582             :                  * /proc. This can never actually happen, but let's
     583             :                  * better be safe than sorry, and do an extra check
     584             :                  * here. */
     585          26 :                 assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
     586             : 
     587             :                 /* Try to use the EUID, if we have it. */
     588          13 :                 r = sd_bus_creds_get_euid(creds, &sender_uid);
     589          13 :                 if (r < 0)
     590           0 :                         r = sd_bus_creds_get_uid(creds, &sender_uid);
     591             : 
     592          13 :                 if (r >= 0) {
     593             :                         /* Sender has same UID as us, then let's grant access */
     594          13 :                         if (sender_uid == our_uid)
     595          13 :                                 return 1;
     596             : 
     597             :                         /* Sender is root, we are not root. */
     598           0 :                         if (our_uid != 0 && sender_uid == 0)
     599           0 :                                 return 1;
     600             :                 }
     601             :         }
     602             : 
     603           0 :         return 0;
     604             : }
     605             : 
     606             : #define make_expression(sender, path, interface, member)        \
     607             :         strjoina(                                               \
     608             :                 "type='signal'",                                \
     609             :                 sender ? ",sender='" : "",                      \
     610             :                 sender ?: "",                                   \
     611             :                 sender ? "'" : "",                              \
     612             :                 path ? ",path='" : "",                          \
     613             :                 path ?: "",                                     \
     614             :                 path ? "'" : "",                                \
     615             :                 interface ? ",interface='" : "",                \
     616             :                 interface ?: "",                                \
     617             :                 interface ? "'" : "",                           \
     618             :                 member ? ",member='" : "",                      \
     619             :                 member ?: "",                                   \
     620             :                 member ? "'" : ""                               \
     621             :         )
     622             : 
     623           1 : _public_ int sd_bus_match_signal(
     624             :                 sd_bus *bus,
     625             :                 sd_bus_slot **ret,
     626             :                 const char *sender,
     627             :                 const char *path,
     628             :                 const char *interface,
     629             :                 const char *member,
     630             :                 sd_bus_message_handler_t callback,
     631             :                 void *userdata) {
     632             : 
     633             :         const char *expression;
     634             : 
     635           1 :         assert_return(bus, -EINVAL);
     636           1 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     637           1 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     638           1 :         assert_return(!sender || service_name_is_valid(sender), -EINVAL);
     639           1 :         assert_return(!path || object_path_is_valid(path), -EINVAL);
     640           1 :         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
     641           1 :         assert_return(!member || member_name_is_valid(member), -EINVAL);
     642             : 
     643          27 :         expression = make_expression(sender, path, interface, member);
     644             : 
     645           1 :         return sd_bus_add_match(bus, ret, expression, callback, userdata);
     646             : }
     647             : 
     648          26 : _public_ int sd_bus_match_signal_async(
     649             :                 sd_bus *bus,
     650             :                 sd_bus_slot **ret,
     651             :                 const char *sender,
     652             :                 const char *path,
     653             :                 const char *interface,
     654             :                 const char *member,
     655             :                 sd_bus_message_handler_t callback,
     656             :                 sd_bus_message_handler_t install_callback,
     657             :                 void *userdata) {
     658             : 
     659             :         const char *expression;
     660             : 
     661          26 :         assert_return(bus, -EINVAL);
     662          26 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     663          26 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     664          26 :         assert_return(!sender || service_name_is_valid(sender), -EINVAL);
     665          26 :         assert_return(!path || object_path_is_valid(path), -EINVAL);
     666          26 :         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
     667          26 :         assert_return(!member || member_name_is_valid(member), -EINVAL);
     668             : 
     669         702 :         expression = make_expression(sender, path, interface, member);
     670             : 
     671          26 :         return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata);
     672             : }

Generated by: LCOV version 1.14