LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-control.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 131 445 29.4 %
Date: 2019-08-22 15:41:25 Functions: 9 16 56.2 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #if HAVE_VALGRIND_MEMCHECK_H
       4             : #include <valgrind/memcheck.h>
       5             : #endif
       6             : 
       7             : #include <errno.h>
       8             : #include <stddef.h>
       9             : 
      10             : #include "sd-bus.h"
      11             : 
      12             : #include "alloc-util.h"
      13             : #include "bus-control.h"
      14             : #include "bus-internal.h"
      15             : #include "bus-message.h"
      16             : #include "bus-util.h"
      17             : #include "capability-util.h"
      18             : #include "process-util.h"
      19             : #include "stdio-util.h"
      20             : #include "string-util.h"
      21             : #include "strv.h"
      22             : #include "user-util.h"
      23             : 
      24           3 : _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
      25             :         int r;
      26             : 
      27           3 :         assert_return(bus, -EINVAL);
      28           3 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
      29           3 :         assert_return(unique, -EINVAL);
      30           3 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      31             : 
      32           3 :         if (!bus->bus_client)
      33           0 :                 return -EINVAL;
      34             : 
      35           3 :         r = bus_ensure_running(bus);
      36           3 :         if (r < 0)
      37           0 :                 return r;
      38             : 
      39           3 :         *unique = bus->unique_name;
      40           3 :         return 0;
      41             : }
      42             : 
      43           2 : static int validate_request_name_parameters(
      44             :                 sd_bus *bus,
      45             :                 const char *name,
      46             :                 uint64_t flags,
      47             :                 uint32_t *ret_param) {
      48             : 
      49           2 :         uint32_t param = 0;
      50             : 
      51           2 :         assert(bus);
      52           2 :         assert(name);
      53           2 :         assert(ret_param);
      54             : 
      55           2 :         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
      56           2 :         assert_return(service_name_is_valid(name), -EINVAL);
      57           2 :         assert_return(name[0] != ':', -EINVAL);
      58             : 
      59           2 :         if (!bus->bus_client)
      60           0 :                 return -EINVAL;
      61             : 
      62             :         /* Don't allow requesting the special driver and local names */
      63           2 :         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
      64           0 :                 return -EINVAL;
      65             : 
      66           2 :         if (!BUS_IS_OPEN(bus->state))
      67           0 :                 return -ENOTCONN;
      68             : 
      69           2 :         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
      70           0 :                 param |= BUS_NAME_ALLOW_REPLACEMENT;
      71           2 :         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
      72           0 :                 param |= BUS_NAME_REPLACE_EXISTING;
      73           2 :         if (!(flags & SD_BUS_NAME_QUEUE))
      74           2 :                 param |= BUS_NAME_DO_NOT_QUEUE;
      75             : 
      76           2 :         *ret_param = param;
      77             : 
      78           2 :         return 0;
      79             : }
      80             : 
      81           1 : _public_ int sd_bus_request_name(
      82             :                 sd_bus *bus,
      83             :                 const char *name,
      84             :                 uint64_t flags) {
      85             : 
      86           1 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
      87           1 :         uint32_t ret, param = 0;
      88             :         int r;
      89             : 
      90           1 :         assert_return(bus, -EINVAL);
      91           1 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
      92           1 :         assert_return(name, -EINVAL);
      93           1 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      94             : 
      95           1 :         r = validate_request_name_parameters(bus, name, flags, &param);
      96           1 :         if (r < 0)
      97           0 :                 return r;
      98             : 
      99           1 :         r = sd_bus_call_method(
     100             :                         bus,
     101             :                         "org.freedesktop.DBus",
     102             :                         "/org/freedesktop/DBus",
     103             :                         "org.freedesktop.DBus",
     104             :                         "RequestName",
     105             :                         NULL,
     106             :                         &reply,
     107             :                         "su",
     108             :                         name,
     109             :                         param);
     110           1 :         if (r < 0)
     111           0 :                 return r;
     112             : 
     113           1 :         r = sd_bus_message_read(reply, "u", &ret);
     114           1 :         if (r < 0)
     115           0 :                 return r;
     116             : 
     117           1 :         switch (ret) {
     118             : 
     119           0 :         case BUS_NAME_ALREADY_OWNER:
     120           0 :                 return -EALREADY;
     121             : 
     122           0 :         case BUS_NAME_EXISTS:
     123           0 :                 return -EEXIST;
     124             : 
     125           0 :         case BUS_NAME_IN_QUEUE:
     126           0 :                 return 0;
     127             : 
     128           1 :         case BUS_NAME_PRIMARY_OWNER:
     129           1 :                 return 1;
     130             :         }
     131             : 
     132           0 :         return -EIO;
     133             : }
     134             : 
     135           0 : static int default_request_name_handler(
     136             :                 sd_bus_message *m,
     137             :                 void *userdata,
     138             :                 sd_bus_error *ret_error) {
     139             : 
     140             :         uint32_t ret;
     141             :         int r;
     142             : 
     143           0 :         assert(m);
     144             : 
     145           0 :         if (sd_bus_message_is_method_error(m, NULL)) {
     146           0 :                 log_debug_errno(sd_bus_message_get_errno(m),
     147             :                                 "Unable to request name, failing connection: %s",
     148             :                                 sd_bus_message_get_error(m)->message);
     149             : 
     150           0 :                 bus_enter_closing(sd_bus_message_get_bus(m));
     151           0 :                 return 1;
     152             :         }
     153             : 
     154           0 :         r = sd_bus_message_read(m, "u", &ret);
     155           0 :         if (r < 0)
     156           0 :                 return r;
     157             : 
     158           0 :         switch (ret) {
     159             : 
     160           0 :         case BUS_NAME_ALREADY_OWNER:
     161           0 :                 log_debug("Already owner of requested service name, ignoring.");
     162           0 :                 return 1;
     163             : 
     164           0 :         case BUS_NAME_IN_QUEUE:
     165           0 :                 log_debug("In queue for requested service name.");
     166           0 :                 return 1;
     167             : 
     168           0 :         case BUS_NAME_PRIMARY_OWNER:
     169           0 :                 log_debug("Successfully acquired requested service name.");
     170           0 :                 return 1;
     171             : 
     172           0 :         case BUS_NAME_EXISTS:
     173           0 :                 log_debug("Requested service name already owned, failing connection.");
     174           0 :                 bus_enter_closing(sd_bus_message_get_bus(m));
     175           0 :                 return 1;
     176             :         }
     177             : 
     178           0 :         log_debug("Unexpected response from RequestName(), failing connection.");
     179           0 :         bus_enter_closing(sd_bus_message_get_bus(m));
     180           0 :         return 1;
     181             : }
     182             : 
     183           1 : _public_ int sd_bus_request_name_async(
     184             :                 sd_bus *bus,
     185             :                 sd_bus_slot **ret_slot,
     186             :                 const char *name,
     187             :                 uint64_t flags,
     188             :                 sd_bus_message_handler_t callback,
     189             :                 void *userdata) {
     190             : 
     191           1 :         uint32_t param = 0;
     192             :         int r;
     193             : 
     194           1 :         assert_return(bus, -EINVAL);
     195           1 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     196           1 :         assert_return(name, -EINVAL);
     197           1 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     198             : 
     199           1 :         r = validate_request_name_parameters(bus, name, flags, &param);
     200           1 :         if (r < 0)
     201           0 :                 return r;
     202             : 
     203           1 :         return sd_bus_call_method_async(
     204             :                         bus,
     205             :                         ret_slot,
     206             :                         "org.freedesktop.DBus",
     207             :                         "/org/freedesktop/DBus",
     208             :                         "org.freedesktop.DBus",
     209             :                         "RequestName",
     210           1 :                         callback ?: default_request_name_handler,
     211             :                         userdata,
     212             :                         "su",
     213             :                         name,
     214             :                         param);
     215             : }
     216             : 
     217           0 : static int validate_release_name_parameters(
     218             :                 sd_bus *bus,
     219             :                 const char *name) {
     220             : 
     221           0 :         assert(bus);
     222           0 :         assert(name);
     223             : 
     224           0 :         assert_return(service_name_is_valid(name), -EINVAL);
     225           0 :         assert_return(name[0] != ':', -EINVAL);
     226             : 
     227           0 :         if (!bus->bus_client)
     228           0 :                 return -EINVAL;
     229             : 
     230             :         /* Don't allow releasing the special driver and local names */
     231           0 :         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
     232           0 :                 return -EINVAL;
     233             : 
     234           0 :         if (!BUS_IS_OPEN(bus->state))
     235           0 :                 return -ENOTCONN;
     236             : 
     237           0 :         return 0;
     238             : }
     239             : 
     240           0 : _public_ int sd_bus_release_name(
     241             :                 sd_bus *bus,
     242             :                 const char *name) {
     243             : 
     244           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     245             :         uint32_t ret;
     246             :         int r;
     247             : 
     248           0 :         assert_return(bus, -EINVAL);
     249           0 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     250           0 :         assert_return(name, -EINVAL);
     251           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     252             : 
     253           0 :         r = validate_release_name_parameters(bus, name);
     254           0 :         if (r < 0)
     255           0 :                 return r;
     256             : 
     257           0 :         r = sd_bus_call_method(
     258             :                         bus,
     259             :                         "org.freedesktop.DBus",
     260             :                         "/org/freedesktop/DBus",
     261             :                         "org.freedesktop.DBus",
     262             :                         "ReleaseName",
     263             :                         NULL,
     264             :                         &reply,
     265             :                         "s",
     266             :                         name);
     267           0 :         if (r < 0)
     268           0 :                 return r;
     269             : 
     270           0 :         r = sd_bus_message_read(reply, "u", &ret);
     271           0 :         if (r < 0)
     272           0 :                 return r;
     273             : 
     274           0 :         switch (ret) {
     275             : 
     276           0 :         case BUS_NAME_NON_EXISTENT:
     277           0 :                 return -ESRCH;
     278             : 
     279           0 :         case BUS_NAME_NOT_OWNER:
     280           0 :                 return -EADDRINUSE;
     281             : 
     282           0 :         case BUS_NAME_RELEASED:
     283           0 :                 return 0;
     284             :         }
     285             : 
     286           0 :         return -EIO;
     287             : }
     288             : 
     289           0 : static int default_release_name_handler(
     290             :                 sd_bus_message *m,
     291             :                 void *userdata,
     292             :                 sd_bus_error *ret_error) {
     293             : 
     294             :         uint32_t ret;
     295             :         int r;
     296             : 
     297           0 :         assert(m);
     298             : 
     299           0 :         if (sd_bus_message_is_method_error(m, NULL)) {
     300           0 :                 log_debug_errno(sd_bus_message_get_errno(m),
     301             :                                 "Unable to release name, failing connection: %s",
     302             :                                 sd_bus_message_get_error(m)->message);
     303             : 
     304           0 :                 bus_enter_closing(sd_bus_message_get_bus(m));
     305           0 :                 return 1;
     306             :         }
     307             : 
     308           0 :         r = sd_bus_message_read(m, "u", &ret);
     309           0 :         if (r < 0)
     310           0 :                 return r;
     311             : 
     312           0 :         switch (ret) {
     313             : 
     314           0 :         case BUS_NAME_NON_EXISTENT:
     315           0 :                 log_debug("Name asked to release is not taken currently, ignoring.");
     316           0 :                 return 1;
     317             : 
     318           0 :         case BUS_NAME_NOT_OWNER:
     319           0 :                 log_debug("Name asked to release is owned by somebody else, ignoring.");
     320           0 :                 return 1;
     321             : 
     322           0 :         case BUS_NAME_RELEASED:
     323           0 :                 log_debug("Name successfully released.");
     324           0 :                 return 1;
     325             :         }
     326             : 
     327           0 :         log_debug("Unexpected response from ReleaseName(), failing connection.");
     328           0 :         bus_enter_closing(sd_bus_message_get_bus(m));
     329           0 :         return 1;
     330             : }
     331             : 
     332           0 : _public_ int sd_bus_release_name_async(
     333             :                 sd_bus *bus,
     334             :                 sd_bus_slot **ret_slot,
     335             :                 const char *name,
     336             :                 sd_bus_message_handler_t callback,
     337             :                 void *userdata) {
     338             : 
     339             :         int r;
     340             : 
     341           0 :         assert_return(bus, -EINVAL);
     342           0 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     343           0 :         assert_return(name, -EINVAL);
     344           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     345             : 
     346           0 :         r = validate_release_name_parameters(bus, name);
     347           0 :         if (r < 0)
     348           0 :                 return r;
     349             : 
     350           0 :         return sd_bus_call_method_async(
     351             :                         bus,
     352             :                         ret_slot,
     353             :                         "org.freedesktop.DBus",
     354             :                         "/org/freedesktop/DBus",
     355             :                         "org.freedesktop.DBus",
     356             :                         "ReleaseName",
     357           0 :                         callback ?: default_release_name_handler,
     358             :                         userdata,
     359             :                         "s",
     360             :                         name);
     361             : }
     362             : 
     363           0 : _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
     364           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     365           0 :         _cleanup_strv_free_ char **x = NULL, **y = NULL;
     366             :         int r;
     367             : 
     368           0 :         assert_return(bus, -EINVAL);
     369           0 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     370           0 :         assert_return(acquired || activatable, -EINVAL);
     371           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     372             : 
     373           0 :         if (!bus->bus_client)
     374           0 :                 return -EINVAL;
     375             : 
     376           0 :         if (!BUS_IS_OPEN(bus->state))
     377           0 :                 return -ENOTCONN;
     378             : 
     379           0 :         if (acquired) {
     380           0 :                 r = sd_bus_call_method(
     381             :                                 bus,
     382             :                                 "org.freedesktop.DBus",
     383             :                                 "/org/freedesktop/DBus",
     384             :                                 "org.freedesktop.DBus",
     385             :                                 "ListNames",
     386             :                                 NULL,
     387             :                                 &reply,
     388             :                                 NULL);
     389           0 :                 if (r < 0)
     390           0 :                         return r;
     391             : 
     392           0 :                 r = sd_bus_message_read_strv(reply, &x);
     393           0 :                 if (r < 0)
     394           0 :                         return r;
     395             : 
     396           0 :                 reply = sd_bus_message_unref(reply);
     397             :         }
     398             : 
     399           0 :         if (activatable) {
     400           0 :                 r = sd_bus_call_method(
     401             :                                 bus,
     402             :                                 "org.freedesktop.DBus",
     403             :                                 "/org/freedesktop/DBus",
     404             :                                 "org.freedesktop.DBus",
     405             :                                 "ListActivatableNames",
     406             :                                 NULL,
     407             :                                 &reply,
     408             :                                 NULL);
     409           0 :                 if (r < 0)
     410           0 :                         return r;
     411             : 
     412           0 :                 r = sd_bus_message_read_strv(reply, &y);
     413           0 :                 if (r < 0)
     414           0 :                         return r;
     415             : 
     416           0 :                 *activatable = TAKE_PTR(y);
     417             :         }
     418             : 
     419           0 :         if (acquired)
     420           0 :                 *acquired = TAKE_PTR(x);
     421             : 
     422           0 :         return 0;
     423             : }
     424             : 
     425           2 : _public_ int sd_bus_get_name_creds(
     426             :                 sd_bus *bus,
     427             :                 const char *name,
     428             :                 uint64_t mask,
     429             :                 sd_bus_creds **creds) {
     430             : 
     431           2 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
     432           2 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
     433             :         const char *unique;
     434           2 :         pid_t pid = 0;
     435             :         int r;
     436             : 
     437           2 :         assert_return(bus, -EINVAL);
     438           2 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     439           2 :         assert_return(name, -EINVAL);
     440           2 :         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
     441           2 :         assert_return(mask == 0 || creds, -EINVAL);
     442           2 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     443           2 :         assert_return(service_name_is_valid(name), -EINVAL);
     444             : 
     445           2 :         if (!bus->bus_client)
     446           0 :                 return -EINVAL;
     447             : 
     448             :         /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
     449             :          * going to match. */
     450           2 :         if (!bus->is_local)
     451           0 :                 mask &= ~SD_BUS_CREDS_AUGMENT;
     452             : 
     453           2 :         if (streq(name, "org.freedesktop.DBus.Local"))
     454           0 :                 return -EINVAL;
     455             : 
     456           2 :         if (streq(name, "org.freedesktop.DBus"))
     457           0 :                 return sd_bus_get_owner_creds(bus, mask, creds);
     458             : 
     459           2 :         if (!BUS_IS_OPEN(bus->state))
     460           0 :                 return -ENOTCONN;
     461             : 
     462             :         /* If the name is unique anyway, we can use it directly */
     463           2 :         unique = name[0] == ':' ? name : NULL;
     464             : 
     465             :         /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just
     466             :          * wants to check whether a name exists */
     467           2 :         if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) {
     468           2 :                 r = sd_bus_call_method(
     469             :                                 bus,
     470             :                                 "org.freedesktop.DBus",
     471             :                                 "/org/freedesktop/DBus",
     472             :                                 "org.freedesktop.DBus",
     473             :                                 "GetNameOwner",
     474             :                                 NULL,
     475             :                                 &reply_unique,
     476             :                                 "s",
     477             :                                 name);
     478           2 :                 if (r < 0)
     479           0 :                         return r;
     480             : 
     481           2 :                 r = sd_bus_message_read(reply_unique, "s", &unique);
     482           2 :                 if (r < 0)
     483           0 :                         return r;
     484             :         }
     485             : 
     486           2 :         if (mask != 0) {
     487           0 :                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     488             :                 bool need_pid, need_uid, need_selinux, need_separate_calls;
     489             : 
     490           0 :                 c = bus_creds_new();
     491           0 :                 if (!c)
     492           0 :                         return -ENOMEM;
     493             : 
     494           0 :                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
     495           0 :                         c->unique_name = strdup(unique);
     496           0 :                         if (!c->unique_name)
     497           0 :                                 return -ENOMEM;
     498             : 
     499           0 :                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
     500             :                 }
     501             : 
     502           0 :                 need_pid = (mask & SD_BUS_CREDS_PID) ||
     503           0 :                         ((mask & SD_BUS_CREDS_AUGMENT) &&
     504           0 :                          (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
     505             :                                   SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
     506             :                                   SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
     507             :                                   SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
     508             :                                   SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
     509             :                                   SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
     510             :                                   SD_BUS_CREDS_SELINUX_CONTEXT|
     511             :                                   SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
     512           0 :                 need_uid = mask & SD_BUS_CREDS_EUID;
     513           0 :                 need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
     514             : 
     515           0 :                 if (need_pid + need_uid + need_selinux > 1) {
     516             : 
     517             :                         /* If we need more than one of the credentials, then use GetConnectionCredentials() */
     518             : 
     519           0 :                         r = sd_bus_call_method(
     520             :                                         bus,
     521             :                                         "org.freedesktop.DBus",
     522             :                                         "/org/freedesktop/DBus",
     523             :                                         "org.freedesktop.DBus",
     524             :                                         "GetConnectionCredentials",
     525             :                                         &error,
     526             :                                         &reply,
     527             :                                         "s",
     528           0 :                                         unique ?: name);
     529             : 
     530           0 :                         if (r < 0) {
     531             : 
     532           0 :                                 if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
     533           0 :                                         return r;
     534             : 
     535             :                                 /* If we got an unknown method error, fall back to the individual calls... */
     536           0 :                                 need_separate_calls = true;
     537           0 :                                 sd_bus_error_free(&error);
     538             : 
     539             :                         } else {
     540           0 :                                 need_separate_calls = false;
     541             : 
     542           0 :                                 r = sd_bus_message_enter_container(reply, 'a', "{sv}");
     543           0 :                                 if (r < 0)
     544           0 :                                         return r;
     545             : 
     546           0 :                                 for (;;) {
     547             :                                         const char *m;
     548             : 
     549           0 :                                         r = sd_bus_message_enter_container(reply, 'e', "sv");
     550           0 :                                         if (r < 0)
     551           0 :                                                 return r;
     552           0 :                                         if (r == 0)
     553           0 :                                                 break;
     554             : 
     555           0 :                                         r = sd_bus_message_read(reply, "s", &m);
     556           0 :                                         if (r < 0)
     557           0 :                                                 return r;
     558             : 
     559           0 :                                         if (need_uid && streq(m, "UnixUserID")) {
     560             :                                                 uint32_t u;
     561             : 
     562           0 :                                                 r = sd_bus_message_read(reply, "v", "u", &u);
     563           0 :                                                 if (r < 0)
     564           0 :                                                         return r;
     565             : 
     566           0 :                                                 c->euid = u;
     567           0 :                                                 c->mask |= SD_BUS_CREDS_EUID;
     568             : 
     569           0 :                                         } else if (need_pid && streq(m, "ProcessID")) {
     570             :                                                 uint32_t p;
     571             : 
     572           0 :                                                 r = sd_bus_message_read(reply, "v", "u", &p);
     573           0 :                                                 if (r < 0)
     574           0 :                                                         return r;
     575             : 
     576           0 :                                                 pid = p;
     577           0 :                                                 if (mask & SD_BUS_CREDS_PID) {
     578           0 :                                                         c->pid = p;
     579           0 :                                                         c->mask |= SD_BUS_CREDS_PID;
     580             :                                                 }
     581             : 
     582           0 :                                         } else if (need_selinux && streq(m, "LinuxSecurityLabel")) {
     583           0 :                                                 const void *p = NULL;
     584           0 :                                                 size_t sz = 0;
     585             : 
     586           0 :                                                 r = sd_bus_message_enter_container(reply, 'v', "ay");
     587           0 :                                                 if (r < 0)
     588           0 :                                                         return r;
     589             : 
     590           0 :                                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
     591           0 :                                                 if (r < 0)
     592           0 :                                                         return r;
     593             : 
     594           0 :                                                 free(c->label);
     595           0 :                                                 c->label = strndup(p, sz);
     596           0 :                                                 if (!c->label)
     597           0 :                                                         return -ENOMEM;
     598             : 
     599           0 :                                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     600             : 
     601           0 :                                                 r = sd_bus_message_exit_container(reply);
     602           0 :                                                 if (r < 0)
     603           0 :                                                         return r;
     604             :                                         } else {
     605           0 :                                                 r = sd_bus_message_skip(reply, "v");
     606           0 :                                                 if (r < 0)
     607           0 :                                                         return r;
     608             :                                         }
     609             : 
     610           0 :                                         r = sd_bus_message_exit_container(reply);
     611           0 :                                         if (r < 0)
     612           0 :                                                 return r;
     613             :                                 }
     614             : 
     615           0 :                                 r = sd_bus_message_exit_container(reply);
     616           0 :                                 if (r < 0)
     617           0 :                                         return r;
     618             : 
     619           0 :                                 if (need_pid && pid == 0)
     620           0 :                                         return -EPROTO;
     621             :                         }
     622             : 
     623             :                 } else /* When we only need a single field, then let's use separate calls */
     624           0 :                         need_separate_calls = true;
     625             : 
     626           0 :                 if (need_separate_calls) {
     627           0 :                         if (need_pid) {
     628             :                                 uint32_t u;
     629             : 
     630           0 :                                 r = sd_bus_call_method(
     631             :                                                 bus,
     632             :                                                 "org.freedesktop.DBus",
     633             :                                                 "/org/freedesktop/DBus",
     634             :                                                 "org.freedesktop.DBus",
     635             :                                                 "GetConnectionUnixProcessID",
     636             :                                                 NULL,
     637             :                                                 &reply,
     638             :                                                 "s",
     639           0 :                                                 unique ?: name);
     640           0 :                                 if (r < 0)
     641           0 :                                         return r;
     642             : 
     643           0 :                                 r = sd_bus_message_read(reply, "u", &u);
     644           0 :                                 if (r < 0)
     645           0 :                                         return r;
     646             : 
     647           0 :                                 pid = u;
     648           0 :                                 if (mask & SD_BUS_CREDS_PID) {
     649           0 :                                         c->pid = u;
     650           0 :                                         c->mask |= SD_BUS_CREDS_PID;
     651             :                                 }
     652             : 
     653           0 :                                 reply = sd_bus_message_unref(reply);
     654             :                         }
     655             : 
     656           0 :                         if (need_uid) {
     657             :                                 uint32_t u;
     658             : 
     659           0 :                                 r = sd_bus_call_method(
     660             :                                                 bus,
     661             :                                                 "org.freedesktop.DBus",
     662             :                                                 "/org/freedesktop/DBus",
     663             :                                                 "org.freedesktop.DBus",
     664             :                                                 "GetConnectionUnixUser",
     665             :                                                 NULL,
     666             :                                                 &reply,
     667             :                                                 "s",
     668           0 :                                                 unique ?: name);
     669           0 :                                 if (r < 0)
     670           0 :                                         return r;
     671             : 
     672           0 :                                 r = sd_bus_message_read(reply, "u", &u);
     673           0 :                                 if (r < 0)
     674           0 :                                         return r;
     675             : 
     676           0 :                                 c->euid = u;
     677           0 :                                 c->mask |= SD_BUS_CREDS_EUID;
     678             : 
     679           0 :                                 reply = sd_bus_message_unref(reply);
     680             :                         }
     681             : 
     682           0 :                         if (need_selinux) {
     683           0 :                                 const void *p = NULL;
     684           0 :                                 size_t sz = 0;
     685             : 
     686           0 :                                 r = sd_bus_call_method(
     687             :                                                 bus,
     688             :                                                 "org.freedesktop.DBus",
     689             :                                                 "/org/freedesktop/DBus",
     690             :                                                 "org.freedesktop.DBus",
     691             :                                                 "GetConnectionSELinuxSecurityContext",
     692             :                                                 &error,
     693             :                                                 &reply,
     694             :                                                 "s",
     695           0 :                                                 unique ?: name);
     696           0 :                                 if (r < 0) {
     697           0 :                                         if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
     698           0 :                                                 return r;
     699             : 
     700             :                                         /* no data is fine */
     701             :                                 } else {
     702           0 :                                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
     703           0 :                                         if (r < 0)
     704           0 :                                                 return r;
     705             : 
     706           0 :                                         c->label = memdup_suffix0(p, sz);
     707           0 :                                         if (!c->label)
     708           0 :                                                 return -ENOMEM;
     709             : 
     710           0 :                                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     711             :                                 }
     712             :                         }
     713             :                 }
     714             : 
     715           0 :                 r = bus_creds_add_more(c, mask, pid, 0);
     716           0 :                 if (r < 0)
     717           0 :                         return r;
     718             :         }
     719             : 
     720           2 :         if (creds)
     721           0 :                 *creds = TAKE_PTR(c);
     722             : 
     723           2 :         return 0;
     724             : }
     725             : 
     726          13 : _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
     727          13 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
     728             :         bool do_label, do_groups;
     729          13 :         pid_t pid = 0;
     730             :         int r;
     731             : 
     732          13 :         assert_return(bus, -EINVAL);
     733          13 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     734          13 :         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
     735          13 :         assert_return(ret, -EINVAL);
     736          13 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     737             : 
     738          13 :         if (!BUS_IS_OPEN(bus->state))
     739           0 :                 return -ENOTCONN;
     740             : 
     741          13 :         if (!bus->is_local)
     742          13 :                 mask &= ~SD_BUS_CREDS_AUGMENT;
     743             : 
     744          13 :         do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
     745          13 :         do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
     746             : 
     747             :         /* Avoid allocating anything if we have no chance of returning useful data */
     748          13 :         if (!bus->ucred_valid && !do_label && !do_groups)
     749           0 :                 return -ENODATA;
     750             : 
     751          13 :         c = bus_creds_new();
     752          13 :         if (!c)
     753           0 :                 return -ENOMEM;
     754             : 
     755          13 :         if (bus->ucred_valid) {
     756          13 :                 if (pid_is_valid(bus->ucred.pid)) {
     757          13 :                         pid = c->pid = bus->ucred.pid;
     758          13 :                         c->mask |= SD_BUS_CREDS_PID & mask;
     759             :                 }
     760             : 
     761          13 :                 if (uid_is_valid(bus->ucred.uid)) {
     762          13 :                         c->euid = bus->ucred.uid;
     763          13 :                         c->mask |= SD_BUS_CREDS_EUID & mask;
     764             :                 }
     765             : 
     766          13 :                 if (gid_is_valid(bus->ucred.gid)) {
     767          13 :                         c->egid = bus->ucred.gid;
     768          13 :                         c->mask |= SD_BUS_CREDS_EGID & mask;
     769             :                 }
     770             :         }
     771             : 
     772          13 :         if (do_label) {
     773           0 :                 c->label = strdup(bus->label);
     774           0 :                 if (!c->label)
     775           0 :                         return -ENOMEM;
     776             : 
     777           0 :                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     778             :         }
     779             : 
     780          13 :         if (do_groups) {
     781           0 :                 c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
     782           0 :                 if (!c->supplementary_gids)
     783           0 :                         return -ENOMEM;
     784             : 
     785           0 :                 c->n_supplementary_gids = bus->n_groups;
     786             : 
     787           0 :                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
     788             :         }
     789             : 
     790          13 :         r = bus_creds_add_more(c, mask, pid, 0);
     791          13 :         if (r < 0)
     792           0 :                 return r;
     793             : 
     794          13 :         *ret = TAKE_PTR(c);
     795             : 
     796          13 :         return 0;
     797             : }
     798             : 
     799             : #define append_eavesdrop(bus, m)                                        \
     800             :         ((bus)->is_monitor                                              \
     801             :          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
     802             :          : (m))
     803             : 
     804           2 : int bus_add_match_internal(
     805             :                 sd_bus *bus,
     806             :                 const char *match,
     807             :                 uint64_t *ret_counter) {
     808             : 
     809           2 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     810             :         const char *e;
     811             :         int r;
     812             : 
     813           2 :         assert(bus);
     814             : 
     815           2 :         if (!bus->bus_client)
     816           0 :                 return -EINVAL;
     817             : 
     818           2 :         e = append_eavesdrop(bus, match);
     819             : 
     820           2 :         r = sd_bus_call_method(
     821             :                         bus,
     822             :                         "org.freedesktop.DBus",
     823             :                         "/org/freedesktop/DBus",
     824             :                         "org.freedesktop.DBus",
     825             :                         "AddMatch",
     826             :                         NULL,
     827             :                         &reply,
     828             :                         "s",
     829             :                         e);
     830           2 :         if (r < 0)
     831           0 :                 return r;
     832             : 
     833             :         /* If the caller asked for it, return the read counter of the reply */
     834           2 :         if (ret_counter)
     835           2 :                 *ret_counter = reply->read_counter;
     836             : 
     837           2 :         return r;
     838             : }
     839             : 
     840          15 : int bus_add_match_internal_async(
     841             :                 sd_bus *bus,
     842             :                 sd_bus_slot **ret_slot,
     843             :                 const char *match,
     844             :                 sd_bus_message_handler_t callback,
     845             :                 void *userdata) {
     846             : 
     847             :         const char *e;
     848             : 
     849          15 :         assert(bus);
     850             : 
     851          15 :         if (!bus->bus_client)
     852           0 :                 return -EINVAL;
     853             : 
     854          15 :         e = append_eavesdrop(bus, match);
     855             : 
     856          15 :         return sd_bus_call_method_async(
     857             :                         bus,
     858             :                         ret_slot,
     859             :                         "org.freedesktop.DBus",
     860             :                         "/org/freedesktop/DBus",
     861             :                         "org.freedesktop.DBus",
     862             :                         "AddMatch",
     863             :                         callback,
     864             :                         userdata,
     865             :                         "s",
     866             :                         e);
     867             : }
     868             : 
     869          17 : int bus_remove_match_internal(
     870             :                 sd_bus *bus,
     871             :                 const char *match) {
     872             : 
     873             :         const char *e;
     874             : 
     875          17 :         assert(bus);
     876          17 :         assert(match);
     877             : 
     878          17 :         if (!bus->bus_client)
     879           0 :                 return -EINVAL;
     880             : 
     881          17 :         e = append_eavesdrop(bus, match);
     882             : 
     883             :         /* Fire and forget */
     884             : 
     885          17 :         return sd_bus_call_method_async(
     886             :                         bus,
     887             :                         NULL,
     888             :                         "org.freedesktop.DBus",
     889             :                         "/org/freedesktop/DBus",
     890             :                         "org.freedesktop.DBus",
     891             :                         "RemoveMatch",
     892             :                         NULL,
     893             :                         NULL,
     894             :                         "s",
     895             :                         e);
     896             : }
     897             : 
     898           0 : _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
     899           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
     900             :         const char *mid;
     901             :         int r;
     902             : 
     903           0 :         assert_return(bus, -EINVAL);
     904           0 :         assert_return(bus = bus_resolve(bus), -ENOPKG);
     905           0 :         assert_return(name, -EINVAL);
     906           0 :         assert_return(machine, -EINVAL);
     907           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     908           0 :         assert_return(service_name_is_valid(name), -EINVAL);
     909             : 
     910           0 :         if (!bus->bus_client)
     911           0 :                 return -EINVAL;
     912             : 
     913           0 :         if (!BUS_IS_OPEN(bus->state))
     914           0 :                 return -ENOTCONN;
     915             : 
     916           0 :         if (streq_ptr(name, bus->unique_name))
     917           0 :                 return sd_id128_get_machine(machine);
     918             : 
     919           0 :         r = sd_bus_message_new_method_call(
     920             :                         bus,
     921             :                         &m,
     922             :                         name,
     923             :                         "/",
     924             :                         "org.freedesktop.DBus.Peer",
     925             :                         "GetMachineId");
     926           0 :         if (r < 0)
     927           0 :                 return r;
     928             : 
     929           0 :         r = sd_bus_message_set_auto_start(m, false);
     930           0 :         if (r < 0)
     931           0 :                 return r;
     932             : 
     933           0 :         r = sd_bus_call(bus, m, 0, NULL, &reply);
     934           0 :         if (r < 0)
     935           0 :                 return r;
     936             : 
     937           0 :         r = sd_bus_message_read(reply, "s", &mid);
     938           0 :         if (r < 0)
     939           0 :                 return r;
     940             : 
     941           0 :         return sd_id128_from_string(mid, machine);
     942             : }

Generated by: LCOV version 1.14