LCOV - code coverage report
Current view: top level - login - logind-user-dbus.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 167 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2011 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <errno.h>
      23             : #include <string.h>
      24             : 
      25             : #include "strv.h"
      26             : #include "bus-util.h"
      27             : #include "logind.h"
      28             : #include "logind-user.h"
      29             : #include "formats-util.h"
      30             : 
      31           0 : static int property_get_display(
      32             :                 sd_bus *bus,
      33             :                 const char *path,
      34             :                 const char *interface,
      35             :                 const char *property,
      36             :                 sd_bus_message *reply,
      37             :                 void *userdata,
      38             :                 sd_bus_error *error) {
      39             : 
      40           0 :         _cleanup_free_ char *p = NULL;
      41           0 :         User *u = userdata;
      42             : 
      43           0 :         assert(bus);
      44           0 :         assert(reply);
      45           0 :         assert(u);
      46             : 
      47           0 :         p = u->display ? session_bus_path(u->display) : strdup("/");
      48           0 :         if (!p)
      49           0 :                 return -ENOMEM;
      50             : 
      51           0 :         return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
      52             : }
      53             : 
      54           0 : static int property_get_state(
      55             :                 sd_bus *bus,
      56             :                 const char *path,
      57             :                 const char *interface,
      58             :                 const char *property,
      59             :                 sd_bus_message *reply,
      60             :                 void *userdata,
      61             :                 sd_bus_error *error) {
      62             : 
      63           0 :         User *u = userdata;
      64             : 
      65           0 :         assert(bus);
      66           0 :         assert(reply);
      67           0 :         assert(u);
      68             : 
      69           0 :         return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
      70             : }
      71             : 
      72           0 : static int property_get_sessions(
      73             :                 sd_bus *bus,
      74             :                 const char *path,
      75             :                 const char *interface,
      76             :                 const char *property,
      77             :                 sd_bus_message *reply,
      78             :                 void *userdata,
      79             :                 sd_bus_error *error) {
      80             : 
      81           0 :         User *u = userdata;
      82             :         Session *session;
      83             :         int r;
      84             : 
      85           0 :         assert(bus);
      86           0 :         assert(reply);
      87           0 :         assert(u);
      88             : 
      89           0 :         r = sd_bus_message_open_container(reply, 'a', "(so)");
      90           0 :         if (r < 0)
      91           0 :                 return r;
      92             : 
      93           0 :         LIST_FOREACH(sessions_by_user, session, u->sessions) {
      94           0 :                 _cleanup_free_ char *p = NULL;
      95             : 
      96           0 :                 p = session_bus_path(session);
      97           0 :                 if (!p)
      98           0 :                         return -ENOMEM;
      99             : 
     100           0 :                 r = sd_bus_message_append(reply, "(so)", session->id, p);
     101           0 :                 if (r < 0)
     102           0 :                         return r;
     103             : 
     104             :         }
     105             : 
     106           0 :         return sd_bus_message_close_container(reply);
     107             : }
     108             : 
     109           0 : static int property_get_idle_hint(
     110             :                 sd_bus *bus,
     111             :                 const char *path,
     112             :                 const char *interface,
     113             :                 const char *property,
     114             :                 sd_bus_message *reply,
     115             :                 void *userdata,
     116             :                 sd_bus_error *error) {
     117             : 
     118           0 :         User *u = userdata;
     119             : 
     120           0 :         assert(bus);
     121           0 :         assert(reply);
     122           0 :         assert(u);
     123             : 
     124           0 :         return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0);
     125             : }
     126             : 
     127           0 : static int property_get_idle_since_hint(
     128             :                 sd_bus *bus,
     129             :                 const char *path,
     130             :                 const char *interface,
     131             :                 const char *property,
     132             :                 sd_bus_message *reply,
     133             :                 void *userdata,
     134             :                 sd_bus_error *error) {
     135             : 
     136           0 :         User *u = userdata;
     137           0 :         dual_timestamp t = DUAL_TIMESTAMP_NULL;
     138             :         uint64_t k;
     139             : 
     140           0 :         assert(bus);
     141           0 :         assert(reply);
     142           0 :         assert(u);
     143             : 
     144           0 :         user_get_idle_hint(u, &t);
     145           0 :         k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
     146             : 
     147           0 :         return sd_bus_message_append(reply, "t", k);
     148             : }
     149             : 
     150           0 : static int property_get_linger(
     151             :                 sd_bus *bus,
     152             :                 const char *path,
     153             :                 const char *interface,
     154             :                 const char *property,
     155             :                 sd_bus_message *reply,
     156             :                 void *userdata,
     157             :                 sd_bus_error *error) {
     158             : 
     159           0 :         User *u = userdata;
     160             :         int r;
     161             : 
     162           0 :         assert(bus);
     163           0 :         assert(reply);
     164           0 :         assert(u);
     165             : 
     166           0 :         r = user_check_linger_file(u);
     167             : 
     168           0 :         return sd_bus_message_append(reply, "b", r > 0);
     169             : }
     170             : 
     171           0 : int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     172           0 :         User *u = userdata;
     173             :         int r;
     174             : 
     175           0 :         assert(message);
     176           0 :         assert(u);
     177             : 
     178           0 :         r = bus_verify_polkit_async(
     179             :                         message,
     180             :                         CAP_KILL,
     181             :                         "org.freedesktop.login1.manage",
     182             :                         false,
     183             :                         u->uid,
     184           0 :                         &u->manager->polkit_registry,
     185             :                         error);
     186           0 :         if (r < 0)
     187           0 :                 return r;
     188           0 :         if (r == 0)
     189           0 :                 return 1; /* Will call us back */
     190             : 
     191           0 :         r = user_stop(u, true);
     192           0 :         if (r < 0)
     193           0 :                 return r;
     194             : 
     195           0 :         return sd_bus_reply_method_return(message, NULL);
     196             : }
     197             : 
     198           0 : int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     199           0 :         User *u = userdata;
     200             :         int32_t signo;
     201             :         int r;
     202             : 
     203           0 :         assert(message);
     204           0 :         assert(u);
     205             : 
     206           0 :         r = bus_verify_polkit_async(
     207             :                         message,
     208             :                         CAP_KILL,
     209             :                         "org.freedesktop.login1.manage",
     210             :                         false,
     211             :                         u->uid,
     212           0 :                         &u->manager->polkit_registry,
     213             :                         error);
     214           0 :         if (r < 0)
     215           0 :                 return r;
     216           0 :         if (r == 0)
     217           0 :                 return 1; /* Will call us back */
     218             : 
     219           0 :         r = sd_bus_message_read(message, "i", &signo);
     220           0 :         if (r < 0)
     221           0 :                 return r;
     222             : 
     223           0 :         if (signo <= 0 || signo >= _NSIG)
     224           0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
     225             : 
     226           0 :         r = user_kill(u, signo);
     227           0 :         if (r < 0)
     228           0 :                 return r;
     229             : 
     230           0 :         return sd_bus_reply_method_return(message, NULL);
     231             : }
     232             : 
     233             : const sd_bus_vtable user_vtable[] = {
     234             :         SD_BUS_VTABLE_START(0),
     235             : 
     236             :         SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST),
     237             :         SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST),
     238             :         SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST),
     239             :         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
     240             :         SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST),
     241             :         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST),
     242             :         SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
     243             :         SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     244             :         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
     245             :         SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     246             :         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     247             :         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     248             :         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     249             :         SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
     250             : 
     251             :         SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
     252             :         SD_BUS_METHOD("Kill", "i", NULL, bus_user_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
     253             : 
     254             :         SD_BUS_VTABLE_END
     255             : };
     256             : 
     257           0 : int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     258           0 :         Manager *m = userdata;
     259             :         uid_t uid;
     260             :         User *user;
     261             :         int r;
     262             : 
     263           0 :         assert(bus);
     264           0 :         assert(path);
     265           0 :         assert(interface);
     266           0 :         assert(found);
     267           0 :         assert(m);
     268             : 
     269           0 :         if (streq(path, "/org/freedesktop/login1/user/self")) {
     270           0 :                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
     271             :                 sd_bus_message *message;
     272             : 
     273           0 :                 message = sd_bus_get_current_message(bus);
     274           0 :                 if (!message)
     275           0 :                         return 0;
     276             : 
     277           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
     278           0 :                 if (r < 0)
     279           0 :                         return r;
     280             : 
     281           0 :                 r = sd_bus_creds_get_owner_uid(creds, &uid);
     282             :         } else {
     283             :                 const char *p;
     284             : 
     285           0 :                 p = startswith(path, "/org/freedesktop/login1/user/_");
     286           0 :                 if (!p)
     287           0 :                         return 0;
     288             : 
     289           0 :                 r = parse_uid(p, &uid);
     290             :         }
     291           0 :         if (r < 0)
     292           0 :                 return 0;
     293             : 
     294           0 :         user = hashmap_get(m->users, UID_TO_PTR(uid));
     295           0 :         if (!user)
     296           0 :                 return 0;
     297             : 
     298           0 :         *found = user;
     299           0 :         return 1;
     300             : }
     301             : 
     302           0 : char *user_bus_path(User *u) {
     303             :         char *s;
     304             : 
     305           0 :         assert(u);
     306             : 
     307           0 :         if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->uid) < 0)
     308           0 :                 return NULL;
     309             : 
     310           0 :         return s;
     311             : }
     312             : 
     313           0 : int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
     314           0 :         _cleanup_strv_free_ char **l = NULL;
     315             :         sd_bus_message *message;
     316           0 :         Manager *m = userdata;
     317             :         User *user;
     318             :         Iterator i;
     319             :         int r;
     320             : 
     321           0 :         assert(bus);
     322           0 :         assert(path);
     323           0 :         assert(nodes);
     324             : 
     325           0 :         HASHMAP_FOREACH(user, m->users, i) {
     326             :                 char *p;
     327             : 
     328           0 :                 p = user_bus_path(user);
     329           0 :                 if (!p)
     330           0 :                         return -ENOMEM;
     331             : 
     332           0 :                 r = strv_consume(&l, p);
     333           0 :                 if (r < 0)
     334           0 :                         return r;
     335             :         }
     336             : 
     337           0 :         message = sd_bus_get_current_message(bus);
     338           0 :         if (message) {
     339           0 :                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
     340             :                 uid_t uid;
     341             : 
     342           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
     343           0 :                 if (r >= 0) {
     344           0 :                         r = sd_bus_creds_get_owner_uid(creds, &uid);
     345           0 :                         if (r >= 0) {
     346           0 :                                 user = hashmap_get(m->users, UID_TO_PTR(uid));
     347           0 :                                 if (user) {
     348           0 :                                         r = strv_extend(&l, "/org/freedesktop/login1/user/self");
     349           0 :                                         if (r < 0)
     350           0 :                                                 return r;
     351             :                                 }
     352             :                         }
     353             :                 }
     354             :         }
     355             : 
     356           0 :         *nodes = l;
     357           0 :         l = NULL;
     358             : 
     359           0 :         return 1;
     360             : }
     361             : 
     362           0 : int user_send_signal(User *u, bool new_user) {
     363           0 :         _cleanup_free_ char *p = NULL;
     364             : 
     365           0 :         assert(u);
     366             : 
     367           0 :         p = user_bus_path(u);
     368           0 :         if (!p)
     369           0 :                 return -ENOMEM;
     370             : 
     371           0 :         return sd_bus_emit_signal(
     372           0 :                         u->manager->bus,
     373             :                         "/org/freedesktop/login1",
     374             :                         "org.freedesktop.login1.Manager",
     375             :                         new_user ? "UserNew" : "UserRemoved",
     376           0 :                         "uo", (uint32_t) u->uid, p);
     377             : }
     378             : 
     379           0 : int user_send_changed(User *u, const char *properties, ...) {
     380           0 :         _cleanup_free_ char *p = NULL;
     381             :         char **l;
     382             : 
     383           0 :         assert(u);
     384             : 
     385           0 :         if (!u->started)
     386           0 :                 return 0;
     387             : 
     388           0 :         p = user_bus_path(u);
     389           0 :         if (!p)
     390           0 :                 return -ENOMEM;
     391             : 
     392           0 :         l = strv_from_stdarg_alloca(properties);
     393             : 
     394           0 :         return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l);
     395             : }

Generated by: LCOV version 1.11