1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-get-properties.h"
8 #include "bus-label.h"
9 #include "bus-polkit.h"
10 #include "bus-util.h"
11 #include "devnum-util.h"
12 #include "fd-util.h"
13 #include "logind-brightness.h"
14 #include "logind-dbus.h"
15 #include "logind-polkit.h"
16 #include "logind-seat-dbus.h"
17 #include "logind-session-dbus.h"
18 #include "logind-session-device.h"
19 #include "logind-session.h"
20 #include "logind-user-dbus.h"
21 #include "logind.h"
22 #include "missing_capability.h"
23 #include "path-util.h"
24 #include "signal-util.h"
25 #include "strv.h"
26 #include "user-util.h"
27 #include "util.h"
28 
property_get_user(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)29 static int property_get_user(
30                 sd_bus *bus,
31                 const char *path,
32                 const char *interface,
33                 const char *property,
34                 sd_bus_message *reply,
35                 void *userdata,
36                 sd_bus_error *error) {
37 
38         _cleanup_free_ char *p = NULL;
39         Session *s = userdata;
40 
41         assert(bus);
42         assert(reply);
43         assert(s);
44 
45         p = user_bus_path(s->user);
46         if (!p)
47                 return -ENOMEM;
48 
49         return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->user_record->uid, p);
50 }
51 
property_get_name(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)52 static int property_get_name(
53                 sd_bus *bus,
54                 const char *path,
55                 const char *interface,
56                 const char *property,
57                 sd_bus_message *reply,
58                 void *userdata,
59                 sd_bus_error *error) {
60 
61         Session *s = userdata;
62 
63         assert(bus);
64         assert(reply);
65         assert(s);
66 
67         return sd_bus_message_append(reply, "s", s->user->user_record->user_name);
68 }
69 
property_get_seat(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)70 static int property_get_seat(
71                 sd_bus *bus,
72                 const char *path,
73                 const char *interface,
74                 const char *property,
75                 sd_bus_message *reply,
76                 void *userdata,
77                 sd_bus_error *error) {
78 
79         _cleanup_free_ char *p = NULL;
80         Session *s = userdata;
81 
82         assert(bus);
83         assert(reply);
84         assert(s);
85 
86         p = s->seat ? seat_bus_path(s->seat) : strdup("/");
87         if (!p)
88                 return -ENOMEM;
89 
90         return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
91 }
92 
93 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
94 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
95 static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active);
96 static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string);
97 
property_get_idle_hint(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)98 static int property_get_idle_hint(
99                 sd_bus *bus,
100                 const char *path,
101                 const char *interface,
102                 const char *property,
103                 sd_bus_message *reply,
104                 void *userdata,
105                 sd_bus_error *error) {
106 
107         Session *s = userdata;
108 
109         assert(bus);
110         assert(reply);
111         assert(s);
112 
113         return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
114 }
115 
property_get_idle_since_hint(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)116 static int property_get_idle_since_hint(
117                 sd_bus *bus,
118                 const char *path,
119                 const char *interface,
120                 const char *property,
121                 sd_bus_message *reply,
122                 void *userdata,
123                 sd_bus_error *error) {
124 
125         Session *s = userdata;
126         dual_timestamp t = DUAL_TIMESTAMP_NULL;
127         uint64_t u;
128         int r;
129 
130         assert(bus);
131         assert(reply);
132         assert(s);
133 
134         r = session_get_idle_hint(s, &t);
135         if (r < 0)
136                 return r;
137 
138         u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
139 
140         return sd_bus_message_append(reply, "t", u);
141 }
142 
property_get_locked_hint(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)143 static int property_get_locked_hint(
144                 sd_bus *bus,
145                 const char *path,
146                 const char *interface,
147                 const char *property,
148                 sd_bus_message *reply,
149                 void *userdata,
150                 sd_bus_error *error) {
151 
152         Session *s = userdata;
153 
154         assert(bus);
155         assert(reply);
156         assert(s);
157 
158         return sd_bus_message_append(reply, "b", session_get_locked_hint(s) > 0);
159 }
160 
bus_session_method_terminate(sd_bus_message * message,void * userdata,sd_bus_error * error)161 int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
162         Session *s = userdata;
163         int r;
164 
165         assert(message);
166         assert(s);
167 
168         r = bus_verify_polkit_async(
169                         message,
170                         CAP_KILL,
171                         "org.freedesktop.login1.manage",
172                         NULL,
173                         false,
174                         s->user->user_record->uid,
175                         &s->manager->polkit_registry,
176                         error);
177         if (r < 0)
178                 return r;
179         if (r == 0)
180                 return 1; /* Will call us back */
181 
182         r = session_stop(s, /* force = */ true);
183         if (r < 0)
184                 return r;
185 
186         return sd_bus_reply_method_return(message, NULL);
187 }
188 
bus_session_method_activate(sd_bus_message * message,void * userdata,sd_bus_error * error)189 int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
190         Session *s = userdata;
191         int r;
192 
193         assert(message);
194         assert(s);
195 
196         r = check_polkit_chvt(message, s->manager, error);
197         if (r < 0)
198                 return r;
199         if (r == 0)
200                 return 1; /* Will call us back */
201 
202         r = session_activate(s);
203         if (r < 0)
204                 return r;
205 
206         return sd_bus_reply_method_return(message, NULL);
207 }
208 
bus_session_method_lock(sd_bus_message * message,void * userdata,sd_bus_error * error)209 int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
210         Session *s = userdata;
211         int r;
212 
213         assert(message);
214         assert(s);
215 
216         r = bus_verify_polkit_async(
217                         message,
218                         CAP_SYS_ADMIN,
219                         "org.freedesktop.login1.lock-sessions",
220                         NULL,
221                         false,
222                         s->user->user_record->uid,
223                         &s->manager->polkit_registry,
224                         error);
225         if (r < 0)
226                 return r;
227         if (r == 0)
228                 return 1; /* Will call us back */
229 
230         r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
231         if (r < 0)
232                 return r;
233 
234         return sd_bus_reply_method_return(message, NULL);
235 }
236 
method_set_idle_hint(sd_bus_message * message,void * userdata,sd_bus_error * error)237 static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
238         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
239         Session *s = userdata;
240         uid_t uid;
241         int r, b;
242 
243         assert(message);
244         assert(s);
245 
246         r = sd_bus_message_read(message, "b", &b);
247         if (r < 0)
248                 return r;
249 
250         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
251         if (r < 0)
252                 return r;
253 
254         r = sd_bus_creds_get_euid(creds, &uid);
255         if (r < 0)
256                 return r;
257 
258         if (uid != 0 && uid != s->user->user_record->uid)
259                 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
260 
261         r = session_set_idle_hint(s, b);
262         if (r == -ENOTTY)
263                 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions.");
264         if (r < 0)
265                 return r;
266 
267         return sd_bus_reply_method_return(message, NULL);
268 }
269 
method_set_locked_hint(sd_bus_message * message,void * userdata,sd_bus_error * error)270 static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
271         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
272         Session *s = userdata;
273         uid_t uid;
274         int r, b;
275 
276         assert(message);
277         assert(s);
278 
279         r = sd_bus_message_read(message, "b", &b);
280         if (r < 0)
281                 return r;
282 
283         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
284         if (r < 0)
285                 return r;
286 
287         r = sd_bus_creds_get_euid(creds, &uid);
288         if (r < 0)
289                 return r;
290 
291         if (uid != 0 && uid != s->user->user_record->uid)
292                 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
293 
294         session_set_locked_hint(s, b);
295 
296         return sd_bus_reply_method_return(message, NULL);
297 }
298 
bus_session_method_kill(sd_bus_message * message,void * userdata,sd_bus_error * error)299 int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
300         Session *s = userdata;
301         const char *swho;
302         int32_t signo;
303         KillWho who;
304         int r;
305 
306         assert(message);
307         assert(s);
308 
309         r = sd_bus_message_read(message, "si", &swho, &signo);
310         if (r < 0)
311                 return r;
312 
313         if (isempty(swho))
314                 who = KILL_ALL;
315         else {
316                 who = kill_who_from_string(swho);
317                 if (who < 0)
318                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
319         }
320 
321         if (!SIGNAL_VALID(signo))
322                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
323 
324         r = bus_verify_polkit_async(
325                         message,
326                         CAP_KILL,
327                         "org.freedesktop.login1.manage",
328                         NULL,
329                         false,
330                         s->user->user_record->uid,
331                         &s->manager->polkit_registry,
332                         error);
333         if (r < 0)
334                 return r;
335         if (r == 0)
336                 return 1; /* Will call us back */
337 
338         r = session_kill(s, who, signo);
339         if (r < 0)
340                 return r;
341 
342         return sd_bus_reply_method_return(message, NULL);
343 }
344 
method_take_control(sd_bus_message * message,void * userdata,sd_bus_error * error)345 static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
346         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
347         Session *s = userdata;
348         int r, force;
349         uid_t uid;
350 
351         assert(message);
352         assert(s);
353 
354         r = sd_bus_message_read(message, "b", &force);
355         if (r < 0)
356                 return r;
357 
358         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
359         if (r < 0)
360                 return r;
361 
362         r = sd_bus_creds_get_euid(creds, &uid);
363         if (r < 0)
364                 return r;
365 
366         if (uid != 0 && (force || uid != s->user->user_record->uid))
367                 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
368 
369         r = session_set_controller(s, sd_bus_message_get_sender(message), force, true);
370         if (r < 0)
371                 return r;
372 
373         return sd_bus_reply_method_return(message, NULL);
374 }
375 
method_release_control(sd_bus_message * message,void * userdata,sd_bus_error * error)376 static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
377         Session *s = userdata;
378 
379         assert(message);
380         assert(s);
381 
382         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
383                 return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
384 
385         session_drop_controller(s);
386 
387         return sd_bus_reply_method_return(message, NULL);
388 }
389 
method_set_type(sd_bus_message * message,void * userdata,sd_bus_error * error)390 static int method_set_type(sd_bus_message *message, void *userdata, sd_bus_error *error) {
391         Session *s = userdata;
392         const char *t;
393         SessionType type;
394         int r;
395 
396         assert(message);
397         assert(s);
398 
399         r = sd_bus_message_read(message, "s", &t);
400         if (r < 0)
401                 return r;
402 
403         type = session_type_from_string(t);
404         if (type < 0)
405                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
406                                          "Invalid session type '%s'", t);
407 
408         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
409                 return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set type");
410 
411         session_set_type(s, type);
412 
413         return sd_bus_reply_method_return(message, NULL);
414 }
415 
method_take_device(sd_bus_message * message,void * userdata,sd_bus_error * error)416 static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
417         Session *s = userdata;
418         uint32_t major, minor;
419         SessionDevice *sd;
420         dev_t dev;
421         int r;
422 
423         assert(message);
424         assert(s);
425 
426         r = sd_bus_message_read(message, "uu", &major, &minor);
427         if (r < 0)
428                 return r;
429 
430         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
431                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
432 
433         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
434                 return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
435 
436         dev = makedev(major, minor);
437         sd = hashmap_get(s->devices, &dev);
438         if (sd)
439                 /* We don't allow retrieving a device multiple times.
440                  * The related ReleaseDevice call is not ref-counted.
441                  * The caller should use dup() if it requires more
442                  * than one fd (it would be functionally
443                  * equivalent). */
444                 return sd_bus_error_set(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
445 
446         r = session_device_new(s, dev, true, &sd);
447         if (r < 0)
448                 return r;
449 
450         r = session_device_save(sd);
451         if (r < 0)
452                 goto error;
453 
454         r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
455         if (r < 0)
456                 goto error;
457 
458         session_save(s);
459         return 1;
460 
461 error:
462         session_device_free(sd);
463         return r;
464 }
465 
method_release_device(sd_bus_message * message,void * userdata,sd_bus_error * error)466 static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
467         Session *s = userdata;
468         uint32_t major, minor;
469         SessionDevice *sd;
470         dev_t dev;
471         int r;
472 
473         assert(message);
474         assert(s);
475 
476         r = sd_bus_message_read(message, "uu", &major, &minor);
477         if (r < 0)
478                 return r;
479 
480         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
481                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
482 
483         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
484                 return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
485 
486         dev = makedev(major, minor);
487         sd = hashmap_get(s->devices, &dev);
488         if (!sd)
489                 return sd_bus_error_set(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
490 
491         session_device_free(sd);
492         session_save(s);
493 
494         return sd_bus_reply_method_return(message, NULL);
495 }
496 
method_pause_device_complete(sd_bus_message * message,void * userdata,sd_bus_error * error)497 static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
498         Session *s = userdata;
499         uint32_t major, minor;
500         SessionDevice *sd;
501         dev_t dev;
502         int r;
503 
504         assert(message);
505         assert(s);
506 
507         r = sd_bus_message_read(message, "uu", &major, &minor);
508         if (r < 0)
509                 return r;
510 
511         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
512                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
513 
514         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
515                 return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
516 
517         dev = makedev(major, minor);
518         sd = hashmap_get(s->devices, &dev);
519         if (!sd)
520                 return sd_bus_error_set(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
521 
522         session_device_complete_pause(sd);
523 
524         return sd_bus_reply_method_return(message, NULL);
525 }
526 
method_set_brightness(sd_bus_message * message,void * userdata,sd_bus_error * error)527 static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus_error *error) {
528         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
529         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
530         const char *subsystem, *name, *seat;
531         Session *s = userdata;
532         uint32_t brightness;
533         uid_t uid;
534         int r;
535 
536         assert(message);
537         assert(s);
538 
539         r = sd_bus_message_read(message, "ssu", &subsystem, &name, &brightness);
540         if (r < 0)
541                 return r;
542 
543         if (!STR_IN_SET(subsystem, "backlight", "leds"))
544                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem);
545         if (!filename_is_valid(name))
546                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not a valid device name %s, refusing.", name);
547 
548         if (!s->seat)
549                 return sd_bus_error_set(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing.");
550         if (s->seat->active != s)
551                 return sd_bus_error_set(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing.");
552 
553         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
554         if (r < 0)
555                 return r;
556 
557         r = sd_bus_creds_get_euid(creds, &uid);
558         if (r < 0)
559                 return r;
560 
561         if (uid != 0 && uid != s->user->user_record->uid)
562                 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness.");
563 
564         r = sd_device_new_from_subsystem_sysname(&d, subsystem, name);
565         if (r < 0)
566                 return sd_bus_error_set_errnof(error, r, "Failed to open device %s:%s: %m", subsystem, name);
567 
568         if (sd_device_get_property_value(d, "ID_SEAT", &seat) >= 0 && !streq_ptr(seat, s->seat->id))
569                 return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Device %s:%s does not belong to your seat %s, refusing.", subsystem, name, s->seat->id);
570 
571         r = manager_write_brightness(s->manager, d, brightness, message);
572         if (r < 0)
573                 return r;
574 
575         return 1;
576 }
577 
session_object_find(sd_bus * bus,const char * path,const char * interface,void * userdata,void ** found,sd_bus_error * error)578 static int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
579         _cleanup_free_ char *e = NULL;
580         sd_bus_message *message;
581         Manager *m = userdata;
582         Session *session;
583         const char *p;
584         int r;
585 
586         assert(bus);
587         assert(path);
588         assert(interface);
589         assert(found);
590         assert(m);
591 
592         p = startswith(path, "/org/freedesktop/login1/session/");
593         if (!p)
594                 return 0;
595 
596         e = bus_label_unescape(p);
597         if (!e)
598                 return -ENOMEM;
599 
600         message = sd_bus_get_current_message(bus);
601 
602         r = manager_get_session_from_creds(m, message, e, error, &session);
603         if (r == -ENXIO) {
604                 sd_bus_error_free(error);
605                 return 0;
606         }
607         if (r < 0)
608                 return r;
609 
610         *found = session;
611         return 1;
612 }
613 
session_bus_path(Session * s)614 char *session_bus_path(Session *s) {
615         _cleanup_free_ char *t = NULL;
616 
617         assert(s);
618 
619         t = bus_label_escape(s->id);
620         if (!t)
621                 return NULL;
622 
623         return strjoin("/org/freedesktop/login1/session/", t);
624 }
625 
session_node_enumerator(sd_bus * bus,const char * path,void * userdata,char *** nodes,sd_bus_error * error)626 static int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
627         _cleanup_strv_free_ char **l = NULL;
628         sd_bus_message *message;
629         Manager *m = userdata;
630         Session *session;
631         int r;
632 
633         assert(bus);
634         assert(path);
635         assert(nodes);
636 
637         HASHMAP_FOREACH(session, m->sessions) {
638                 char *p;
639 
640                 p = session_bus_path(session);
641                 if (!p)
642                         return -ENOMEM;
643 
644                 r = strv_consume(&l, p);
645                 if (r < 0)
646                         return r;
647         }
648 
649         message = sd_bus_get_current_message(bus);
650         if (message) {
651                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
652 
653                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
654                 if (r >= 0) {
655                         bool may_auto = false;
656                         const char *name;
657 
658                         r = sd_bus_creds_get_session(creds, &name);
659                         if (r >= 0) {
660                                 session = hashmap_get(m->sessions, name);
661                                 if (session) {
662                                         r = strv_extend(&l, "/org/freedesktop/login1/session/self");
663                                         if (r < 0)
664                                                 return r;
665 
666                                         may_auto = true;
667                                 }
668                         }
669 
670                         if (!may_auto) {
671                                 uid_t uid;
672 
673                                 r = sd_bus_creds_get_owner_uid(creds, &uid);
674                                 if (r >= 0) {
675                                         User *user;
676 
677                                         user = hashmap_get(m->users, UID_TO_PTR(uid));
678                                         may_auto = user && user->display;
679                                 }
680                         }
681 
682                         if (may_auto) {
683                                 r = strv_extend(&l, "/org/freedesktop/login1/session/auto");
684                                 if (r < 0)
685                                         return r;
686                         }
687                 }
688         }
689 
690         *nodes = TAKE_PTR(l);
691         return 1;
692 }
693 
session_send_signal(Session * s,bool new_session)694 int session_send_signal(Session *s, bool new_session) {
695         _cleanup_free_ char *p = NULL;
696 
697         assert(s);
698 
699         p = session_bus_path(s);
700         if (!p)
701                 return -ENOMEM;
702 
703         return sd_bus_emit_signal(
704                         s->manager->bus,
705                         "/org/freedesktop/login1",
706                         "org.freedesktop.login1.Manager",
707                         new_session ? "SessionNew" : "SessionRemoved",
708                         "so", s->id, p);
709 }
710 
session_send_changed(Session * s,const char * properties,...)711 int session_send_changed(Session *s, const char *properties, ...) {
712         _cleanup_free_ char *p = NULL;
713         char **l;
714 
715         assert(s);
716 
717         if (!s->started)
718                 return 0;
719 
720         p = session_bus_path(s);
721         if (!p)
722                 return -ENOMEM;
723 
724         l = strv_from_stdarg_alloca(properties);
725 
726         return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
727 }
728 
session_send_lock(Session * s,bool lock)729 int session_send_lock(Session *s, bool lock) {
730         _cleanup_free_ char *p = NULL;
731 
732         assert(s);
733 
734         p = session_bus_path(s);
735         if (!p)
736                 return -ENOMEM;
737 
738         return sd_bus_emit_signal(
739                         s->manager->bus,
740                         p,
741                         "org.freedesktop.login1.Session",
742                         lock ? "Lock" : "Unlock",
743                         NULL);
744 }
745 
session_send_lock_all(Manager * m,bool lock)746 int session_send_lock_all(Manager *m, bool lock) {
747         Session *session;
748         int r = 0;
749 
750         assert(m);
751 
752         HASHMAP_FOREACH(session, m->sessions) {
753                 int k;
754 
755                 k = session_send_lock(session, lock);
756                 if (k < 0)
757                         r = k;
758         }
759 
760         return r;
761 }
762 
session_ready(Session * s)763 static bool session_ready(Session *s) {
764         assert(s);
765 
766         /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */
767 
768         return !s->scope_job &&
769                 !s->user->service_job;
770 }
771 
session_send_create_reply(Session * s,sd_bus_error * error)772 int session_send_create_reply(Session *s, sd_bus_error *error) {
773         _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
774         _cleanup_close_ int fifo_fd = -1;
775         _cleanup_free_ char *p = NULL;
776 
777         assert(s);
778 
779         /* This is called after the session scope and the user service were successfully created, and finishes where
780          * bus_manager_create_session() left off. */
781 
782         if (!s->create_message)
783                 return 0;
784 
785         if (!sd_bus_error_is_set(error) && !session_ready(s))
786                 return 0;
787 
788         c = TAKE_PTR(s->create_message);
789         if (error)
790                 return sd_bus_reply_method_error(c, error);
791 
792         fifo_fd = session_create_fifo(s);
793         if (fifo_fd < 0)
794                 return fifo_fd;
795 
796         /* Update the session state file before we notify the client about the result. */
797         session_save(s);
798 
799         p = session_bus_path(s);
800         if (!p)
801                 return -ENOMEM;
802 
803         log_debug("Sending reply about created session: "
804                   "id=%s object_path=%s uid=%u runtime_path=%s "
805                   "session_fd=%d seat=%s vtnr=%u",
806                   s->id,
807                   p,
808                   (uint32_t) s->user->user_record->uid,
809                   s->user->runtime_path,
810                   fifo_fd,
811                   s->seat ? s->seat->id : "",
812                   (uint32_t) s->vtnr);
813 
814         return sd_bus_reply_method_return(
815                         c, "soshusub",
816                         s->id,
817                         p,
818                         s->user->runtime_path,
819                         fifo_fd,
820                         (uint32_t) s->user->user_record->uid,
821                         s->seat ? s->seat->id : "",
822                         (uint32_t) s->vtnr,
823                         false);
824 }
825 
826 static const sd_bus_vtable session_vtable[] = {
827         SD_BUS_VTABLE_START(0),
828 
829         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
830         SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
831         SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
832         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
833         SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
834         SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
835         SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
836         SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
837         SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
838         SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
839         SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
840         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
841         SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
842         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
843         SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
844         SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
845         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
846         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
847         SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
848         SD_BUS_PROPERTY("State", "s", property_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
849         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
850         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
851         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
852         SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
853 
854         SD_BUS_METHOD("Terminate",
855                       NULL,
856                       NULL,
857                       bus_session_method_terminate,
858                       SD_BUS_VTABLE_UNPRIVILEGED),
859         SD_BUS_METHOD("Activate",
860                       NULL,
861                       NULL,
862                       bus_session_method_activate,
863                       SD_BUS_VTABLE_UNPRIVILEGED),
864         SD_BUS_METHOD("Lock",
865                       NULL,
866                       NULL,
867                       bus_session_method_lock,
868                       SD_BUS_VTABLE_UNPRIVILEGED),
869         SD_BUS_METHOD("Unlock",
870                       NULL,
871                       NULL,
872                       bus_session_method_lock,
873                       SD_BUS_VTABLE_UNPRIVILEGED),
874         SD_BUS_METHOD_WITH_ARGS("SetIdleHint",
875                                 SD_BUS_ARGS("b", idle),
876                                 SD_BUS_NO_RESULT,
877                                 method_set_idle_hint,
878                                 SD_BUS_VTABLE_UNPRIVILEGED),
879         SD_BUS_METHOD_WITH_ARGS("SetLockedHint",
880                                 SD_BUS_ARGS("b", locked),
881                                 SD_BUS_NO_RESULT,
882                                 method_set_locked_hint,
883                                 SD_BUS_VTABLE_UNPRIVILEGED),
884         SD_BUS_METHOD_WITH_ARGS("Kill",
885                                 SD_BUS_ARGS("s", who, "i", signal_number),
886                                 SD_BUS_NO_RESULT,
887                                 bus_session_method_kill,
888                                 SD_BUS_VTABLE_UNPRIVILEGED),
889         SD_BUS_METHOD_WITH_ARGS("TakeControl",
890                                 SD_BUS_ARGS("b", force),
891                                 SD_BUS_NO_RESULT,
892                                 method_take_control,
893                                 SD_BUS_VTABLE_UNPRIVILEGED),
894         SD_BUS_METHOD("ReleaseControl",
895                       NULL,
896                       NULL,
897                       method_release_control,
898                       SD_BUS_VTABLE_UNPRIVILEGED),
899         SD_BUS_METHOD_WITH_ARGS("SetType",
900                                 SD_BUS_ARGS("s", type),
901                                 SD_BUS_NO_RESULT,
902                                 method_set_type,
903                                 SD_BUS_VTABLE_UNPRIVILEGED),
904         SD_BUS_METHOD_WITH_ARGS("TakeDevice",
905                                 SD_BUS_ARGS("u", major, "u", minor),
906                                 SD_BUS_RESULT("h", fd, "b", inactive),
907                                 method_take_device,
908                                 SD_BUS_VTABLE_UNPRIVILEGED),
909         SD_BUS_METHOD_WITH_ARGS("ReleaseDevice",
910                                 SD_BUS_ARGS("u", major, "u", minor),
911                                 SD_BUS_NO_RESULT,
912                                 method_release_device,
913                                 SD_BUS_VTABLE_UNPRIVILEGED),
914         SD_BUS_METHOD_WITH_ARGS("PauseDeviceComplete",
915                                 SD_BUS_ARGS("u", major, "u", minor),
916                                 SD_BUS_NO_RESULT,
917                                 method_pause_device_complete,
918                                 SD_BUS_VTABLE_UNPRIVILEGED),
919         SD_BUS_METHOD_WITH_ARGS("SetBrightness",
920                                 SD_BUS_ARGS("s", subsystem, "s", name, "u", brightness),
921                                 SD_BUS_NO_RESULT,
922                                 method_set_brightness,
923                                 SD_BUS_VTABLE_UNPRIVILEGED),
924 
925         SD_BUS_SIGNAL_WITH_ARGS("PauseDevice",
926                                 SD_BUS_ARGS("u", major, "u", minor, "s", type),
927                                 0),
928         SD_BUS_SIGNAL_WITH_ARGS("ResumeDevice",
929                                 SD_BUS_ARGS("u", major, "u", minor, "h", fd),
930                                 0),
931         SD_BUS_SIGNAL("Lock", NULL, 0),
932         SD_BUS_SIGNAL("Unlock", NULL, 0),
933 
934         SD_BUS_VTABLE_END
935 };
936 
937 const BusObjectImplementation session_object = {
938         "/org/freedesktop/login1/session",
939         "org.freedesktop.login1.Session",
940         .fallback_vtables = BUS_FALLBACK_VTABLES({session_vtable, session_object_find}),
941         .node_enumerator = session_node_enumerator,
942 };
943