LCOV - code coverage report
Current view: top level - login - logind-seat-dbus.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 196 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <string.h>
       5             : 
       6             : #include "alloc-util.h"
       7             : #include "bus-common-errors.h"
       8             : #include "bus-label.h"
       9             : #include "bus-util.h"
      10             : #include "logind-dbus.h"
      11             : #include "logind-seat-dbus.h"
      12             : #include "logind-seat.h"
      13             : #include "logind-session-dbus.h"
      14             : #include "logind.h"
      15             : #include "missing_capability.h"
      16             : #include "strv.h"
      17             : #include "user-util.h"
      18             : #include "util.h"
      19             : 
      20           0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_multi_session, "b", Seat, seat_can_multi_session);
      21           0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_tty, "b", Seat, seat_can_tty);
      22           0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_graphical, "b", Seat, seat_can_graphical);
      23             : 
      24           0 : static int property_get_active_session(
      25             :                 sd_bus *bus,
      26             :                 const char *path,
      27             :                 const char *interface,
      28             :                 const char *property,
      29             :                 sd_bus_message *reply,
      30             :                 void *userdata,
      31             :                 sd_bus_error *error) {
      32             : 
      33           0 :         _cleanup_free_ char *p = NULL;
      34           0 :         Seat *s = userdata;
      35             : 
      36           0 :         assert(bus);
      37           0 :         assert(reply);
      38           0 :         assert(s);
      39             : 
      40           0 :         p = s->active ? session_bus_path(s->active) : strdup("/");
      41           0 :         if (!p)
      42           0 :                 return -ENOMEM;
      43             : 
      44           0 :         return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
      45             : }
      46             : 
      47           0 : static int property_get_sessions(
      48             :                 sd_bus *bus,
      49             :                 const char *path,
      50             :                 const char *interface,
      51             :                 const char *property,
      52             :                 sd_bus_message *reply,
      53             :                 void *userdata,
      54             :                 sd_bus_error *error) {
      55             : 
      56           0 :         Seat *s = userdata;
      57             :         Session *session;
      58             :         int r;
      59             : 
      60           0 :         assert(bus);
      61           0 :         assert(reply);
      62           0 :         assert(s);
      63             : 
      64           0 :         r = sd_bus_message_open_container(reply, 'a', "(so)");
      65           0 :         if (r < 0)
      66           0 :                 return r;
      67             : 
      68           0 :         LIST_FOREACH(sessions_by_seat, session, s->sessions) {
      69           0 :                 _cleanup_free_ char *p = NULL;
      70             : 
      71           0 :                 p = session_bus_path(session);
      72           0 :                 if (!p)
      73           0 :                         return -ENOMEM;
      74             : 
      75           0 :                 r = sd_bus_message_append(reply, "(so)", session->id, p);
      76           0 :                 if (r < 0)
      77           0 :                         return r;
      78             : 
      79             :         }
      80             : 
      81           0 :         r = sd_bus_message_close_container(reply);
      82           0 :         if (r < 0)
      83           0 :                 return r;
      84             : 
      85           0 :         return 1;
      86             : }
      87             : 
      88           0 : static int property_get_idle_hint(
      89             :                 sd_bus *bus,
      90             :                 const char *path,
      91             :                 const char *interface,
      92             :                 const char *property,
      93             :                 sd_bus_message *reply,
      94             :                 void *userdata,
      95             :                 sd_bus_error *error) {
      96             : 
      97           0 :         Seat *s = userdata;
      98             : 
      99           0 :         assert(bus);
     100           0 :         assert(reply);
     101           0 :         assert(s);
     102             : 
     103           0 :         return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
     104             : }
     105             : 
     106           0 : static int property_get_idle_since_hint(
     107             :                 sd_bus *bus,
     108             :                 const char *path,
     109             :                 const char *interface,
     110             :                 const char *property,
     111             :                 sd_bus_message *reply,
     112             :                 void *userdata,
     113             :                 sd_bus_error *error) {
     114             : 
     115           0 :         Seat *s = userdata;
     116             :         dual_timestamp t;
     117             :         uint64_t u;
     118             :         int r;
     119             : 
     120           0 :         assert(bus);
     121           0 :         assert(reply);
     122           0 :         assert(s);
     123             : 
     124           0 :         r = seat_get_idle_hint(s, &t);
     125           0 :         if (r < 0)
     126           0 :                 return r;
     127             : 
     128           0 :         u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
     129             : 
     130           0 :         return sd_bus_message_append(reply, "t", u);
     131             : }
     132             : 
     133           0 : int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     134           0 :         Seat *s = userdata;
     135             :         int r;
     136             : 
     137           0 :         assert(message);
     138           0 :         assert(s);
     139             : 
     140           0 :         r = bus_verify_polkit_async(
     141             :                         message,
     142             :                         CAP_KILL,
     143             :                         "org.freedesktop.login1.manage",
     144             :                         NULL,
     145             :                         false,
     146             :                         UID_INVALID,
     147           0 :                         &s->manager->polkit_registry,
     148             :                         error);
     149           0 :         if (r < 0)
     150           0 :                 return r;
     151           0 :         if (r == 0)
     152           0 :                 return 1; /* Will call us back */
     153             : 
     154           0 :         r = seat_stop_sessions(s, true);
     155           0 :         if (r < 0)
     156           0 :                 return r;
     157             : 
     158           0 :         return sd_bus_reply_method_return(message, NULL);
     159             : }
     160             : 
     161           0 : static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     162           0 :         Seat *s = userdata;
     163             :         const char *name;
     164             :         Session *session;
     165             :         int r;
     166             : 
     167           0 :         assert(message);
     168           0 :         assert(s);
     169             : 
     170           0 :         r = sd_bus_message_read(message, "s", &name);
     171           0 :         if (r < 0)
     172           0 :                 return r;
     173             : 
     174           0 :         session = hashmap_get(s->manager->sessions, name);
     175           0 :         if (!session)
     176           0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
     177             : 
     178           0 :         if (session->seat != s)
     179           0 :                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
     180             : 
     181           0 :         r = session_activate(session);
     182           0 :         if (r < 0)
     183           0 :                 return r;
     184             : 
     185           0 :         return sd_bus_reply_method_return(message, NULL);
     186             : }
     187             : 
     188           0 : static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     189           0 :         Seat *s = userdata;
     190             :         unsigned to;
     191             :         int r;
     192             : 
     193           0 :         assert(message);
     194           0 :         assert(s);
     195             : 
     196           0 :         r = sd_bus_message_read(message, "u", &to);
     197           0 :         if (r < 0)
     198           0 :                 return r;
     199             : 
     200           0 :         if (to <= 0)
     201           0 :                 return -EINVAL;
     202             : 
     203           0 :         r = seat_switch_to(s, to);
     204           0 :         if (r < 0)
     205           0 :                 return r;
     206             : 
     207           0 :         return sd_bus_reply_method_return(message, NULL);
     208             : }
     209             : 
     210           0 : static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     211           0 :         Seat *s = userdata;
     212             :         int r;
     213             : 
     214           0 :         assert(message);
     215           0 :         assert(s);
     216             : 
     217           0 :         r = seat_switch_to_next(s);
     218           0 :         if (r < 0)
     219           0 :                 return r;
     220             : 
     221           0 :         return sd_bus_reply_method_return(message, NULL);
     222             : }
     223             : 
     224           0 : static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     225           0 :         Seat *s = userdata;
     226             :         int r;
     227             : 
     228           0 :         assert(message);
     229           0 :         assert(s);
     230             : 
     231           0 :         r = seat_switch_to_previous(s);
     232           0 :         if (r < 0)
     233           0 :                 return r;
     234             : 
     235           0 :         return sd_bus_reply_method_return(message, NULL);
     236             : }
     237             : 
     238             : const sd_bus_vtable seat_vtable[] = {
     239             :         SD_BUS_VTABLE_START(0),
     240             : 
     241             :         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST),
     242             :         SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     243             :         SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     244             :         SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     245             :         SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     246             :         SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0),
     247             :         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     248             :         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     249             :         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     250             : 
     251             :         SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
     252             :         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
     253             :         SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED),
     254             :         SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED),
     255             :         SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED),
     256             : 
     257             :         SD_BUS_VTABLE_END
     258             : };
     259             : 
     260           0 : int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     261           0 :         _cleanup_free_ char *e = NULL;
     262             :         sd_bus_message *message;
     263           0 :         Manager *m = userdata;
     264             :         const char *p;
     265             :         Seat *seat;
     266             :         int r;
     267             : 
     268           0 :         assert(bus);
     269           0 :         assert(path);
     270           0 :         assert(interface);
     271           0 :         assert(found);
     272           0 :         assert(m);
     273             : 
     274           0 :         p = startswith(path, "/org/freedesktop/login1/seat/");
     275           0 :         if (!p)
     276           0 :                 return 0;
     277             : 
     278           0 :         e = bus_label_unescape(p);
     279           0 :         if (!e)
     280           0 :                 return -ENOMEM;
     281             : 
     282           0 :         message = sd_bus_get_current_message(bus);
     283           0 :         if (!message)
     284           0 :                 return 0;
     285             : 
     286           0 :         r = manager_get_seat_from_creds(m, message, e, error, &seat);
     287           0 :         if (r == -ENXIO) {
     288           0 :                 sd_bus_error_free(error);
     289           0 :                 return 0;
     290             :         }
     291           0 :         if (r < 0)
     292           0 :                 return r;
     293             : 
     294           0 :         *found = seat;
     295           0 :         return 1;
     296             : }
     297             : 
     298           0 : char *seat_bus_path(Seat *s) {
     299           0 :         _cleanup_free_ char *t = NULL;
     300             : 
     301           0 :         assert(s);
     302             : 
     303           0 :         t = bus_label_escape(s->id);
     304           0 :         if (!t)
     305           0 :                 return NULL;
     306             : 
     307           0 :         return strjoin("/org/freedesktop/login1/seat/", t);
     308             : }
     309             : 
     310           0 : int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
     311           0 :         _cleanup_strv_free_ char **l = NULL;
     312             :         sd_bus_message *message;
     313           0 :         Manager *m = userdata;
     314             :         Seat *seat;
     315             :         Iterator i;
     316             :         int r;
     317             : 
     318           0 :         assert(bus);
     319           0 :         assert(path);
     320           0 :         assert(nodes);
     321             : 
     322           0 :         HASHMAP_FOREACH(seat, m->seats, i) {
     323             :                 char *p;
     324             : 
     325           0 :                 p = seat_bus_path(seat);
     326           0 :                 if (!p)
     327           0 :                         return -ENOMEM;
     328             : 
     329           0 :                 r = strv_consume(&l, p);
     330           0 :                 if (r < 0)
     331           0 :                         return r;
     332             :         }
     333             : 
     334           0 :         message = sd_bus_get_current_message(bus);
     335           0 :         if (message) {
     336           0 :                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     337             : 
     338           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
     339           0 :                 if (r >= 0) {
     340           0 :                         bool may_auto = false;
     341             :                         const char *name;
     342             : 
     343           0 :                         r = sd_bus_creds_get_session(creds, &name);
     344           0 :                         if (r >= 0) {
     345             :                                 Session *session;
     346             : 
     347           0 :                                 session = hashmap_get(m->sessions, name);
     348           0 :                                 if (session && session->seat) {
     349           0 :                                         r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
     350           0 :                                         if (r < 0)
     351           0 :                                                 return r;
     352             : 
     353           0 :                                         may_auto = true;
     354             :                                 }
     355             :                         }
     356             : 
     357           0 :                         if (!may_auto) {
     358             :                                 uid_t uid;
     359             : 
     360           0 :                                 r = sd_bus_creds_get_owner_uid(creds, &uid);
     361           0 :                                 if (r >= 0) {
     362             :                                         User *user;
     363             : 
     364           0 :                                         user = hashmap_get(m->users, UID_TO_PTR(uid));
     365           0 :                                         may_auto = user && user->display && user->display->seat;
     366             :                                 }
     367             :                         }
     368             : 
     369           0 :                         if (may_auto) {
     370           0 :                                 r = strv_extend(&l, "/org/freedesktop/login1/seat/auto");
     371           0 :                                 if (r < 0)
     372           0 :                                         return r;
     373             :                         }
     374             :                 }
     375             :         }
     376             : 
     377           0 :         *nodes = TAKE_PTR(l);
     378           0 :         return 1;
     379             : }
     380             : 
     381           0 : int seat_send_signal(Seat *s, bool new_seat) {
     382           0 :         _cleanup_free_ char *p = NULL;
     383             : 
     384           0 :         assert(s);
     385             : 
     386           0 :         p = seat_bus_path(s);
     387           0 :         if (!p)
     388           0 :                 return -ENOMEM;
     389             : 
     390           0 :         return sd_bus_emit_signal(
     391           0 :                         s->manager->bus,
     392             :                         "/org/freedesktop/login1",
     393             :                         "org.freedesktop.login1.Manager",
     394             :                         new_seat ? "SeatNew" : "SeatRemoved",
     395             :                         "so", s->id, p);
     396             : }
     397             : 
     398           0 : int seat_send_changed(Seat *s, const char *properties, ...) {
     399           0 :         _cleanup_free_ char *p = NULL;
     400             :         char **l;
     401             : 
     402           0 :         assert(s);
     403             : 
     404           0 :         if (!s->started)
     405           0 :                 return 0;
     406             : 
     407           0 :         p = seat_bus_path(s);
     408           0 :         if (!p)
     409           0 :                 return -ENOMEM;
     410             : 
     411           0 :         l = strv_from_stdarg_alloca(properties);
     412             : 
     413           0 :         return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
     414             : }

Generated by: LCOV version 1.14