chiark / gitweb /
logind: open up most bus calls for unpriviliged processes, using PolicyKit
[elogind.git] / src / login / logind-dbus.c
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 #include <unistd.h>
25 #include <pwd.h>
26
27 #include "sd-id128.h"
28 #include "sd-messages.h"
29 #include "strv.h"
30 #include "mkdir.h"
31 #include "path-util.h"
32 #include "special.h"
33 #include "sleep-config.h"
34 #include "fileio-label.h"
35 #include "label.h"
36 #include "utf8.h"
37 #include "unit-name.h"
38 #include "virt.h"
39 #include "audit.h"
40 #include "bus-util.h"
41 #include "bus-error.h"
42 #include "bus-common-errors.h"
43 #include "udev-util.h"
44 #include "selinux-util.h"
45 #include "logind.h"
46
47 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
48         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
49         Session *session;
50         int r;
51
52         assert(m);
53         assert(message);
54         assert(ret);
55
56         if (isempty(name)) {
57                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
58                 if (r < 0)
59                         return r;
60
61                 r = sd_bus_creds_get_session(creds, &name);
62                 if (r < 0)
63                         return r;
64         }
65
66         session = hashmap_get(m->sessions, name);
67         if (!session)
68                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
69
70         *ret = session;
71         return 0;
72 }
73
74 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
75         User *user;
76         int r;
77
78         assert(m);
79         assert(message);
80         assert(ret);
81
82         if (uid == UID_INVALID) {
83                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
84
85                 /* Note that we get the owner UID of the session, not the actual client UID here! */
86                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
87                 if (r < 0)
88                         return r;
89
90                 r = sd_bus_creds_get_owner_uid(creds, &uid);
91                 if (r < 0)
92                         return r;
93         }
94
95         user = hashmap_get(m->users, UID_TO_PTR(uid));
96         if (!user)
97                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
98
99         *ret = user;
100         return 0;
101 }
102
103 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
104         Seat *seat;
105         int r;
106
107         assert(m);
108         assert(message);
109         assert(ret);
110
111         if (isempty(name)) {
112                 Session *session;
113
114                 r = manager_get_session_from_creds(m, message, NULL, error, &session);
115                 if (r < 0)
116                         return r;
117
118                 seat = session->seat;
119
120                 if (!seat)
121                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
122         } else {
123                 seat = hashmap_get(m->seats, name);
124                 if (!seat)
125                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
126         }
127
128         *ret = seat;
129         return 0;
130 }
131
132 static int property_get_idle_hint(
133                 sd_bus *bus,
134                 const char *path,
135                 const char *interface,
136                 const char *property,
137                 sd_bus_message *reply,
138                 void *userdata,
139                 sd_bus_error *error) {
140
141         Manager *m = userdata;
142
143         assert(bus);
144         assert(reply);
145         assert(m);
146
147         return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
148 }
149
150 static int property_get_idle_since_hint(
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         Manager *m = userdata;
160         dual_timestamp t;
161
162         assert(bus);
163         assert(reply);
164         assert(m);
165
166         manager_get_idle_hint(m, &t);
167
168         return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
169 }
170
171 static int property_get_inhibited(
172                 sd_bus *bus,
173                 const char *path,
174                 const char *interface,
175                 const char *property,
176                 sd_bus_message *reply,
177                 void *userdata,
178                 sd_bus_error *error) {
179
180         Manager *m = userdata;
181         InhibitWhat w;
182
183         assert(bus);
184         assert(reply);
185         assert(m);
186
187         w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
188
189         return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
190 }
191
192 static int property_get_preparing(
193                 sd_bus *bus,
194                 const char *path,
195                 const char *interface,
196                 const char *property,
197                 sd_bus_message *reply,
198                 void *userdata,
199                 sd_bus_error *error) {
200
201         Manager *m = userdata;
202         bool b;
203
204         assert(bus);
205         assert(reply);
206         assert(m);
207
208         if (streq(property, "PreparingForShutdown"))
209                 b = !!(m->action_what & INHIBIT_SHUTDOWN);
210         else
211                 b = !!(m->action_what & INHIBIT_SLEEP);
212
213         return sd_bus_message_append(reply, "b", b);
214 }
215
216 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
217
218 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
219         _cleanup_free_ char *p = NULL;
220         Manager *m = userdata;
221         const char *name;
222         Session *session;
223         int r;
224
225         assert(bus);
226         assert(message);
227         assert(m);
228
229         r = sd_bus_message_read(message, "s", &name);
230         if (r < 0)
231                 return r;
232
233         r = manager_get_session_from_creds(m, message, name, error, &session);
234         if (r < 0)
235                 return r;
236
237         p = session_bus_path(session);
238         if (!p)
239                 return -ENOMEM;
240
241         return sd_bus_reply_method_return(message, "o", p);
242 }
243
244 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
245         _cleanup_free_ char *p = NULL;
246         Session *session = NULL;
247         Manager *m = userdata;
248         pid_t pid;
249         int r;
250
251         assert(bus);
252         assert(message);
253         assert(m);
254
255         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
256
257         r = sd_bus_message_read(message, "u", &pid);
258         if (r < 0)
259                 return r;
260
261         if (pid <= 0) {
262                 r = manager_get_session_from_creds(m, message, NULL, error, &session);
263                 if (r < 0)
264                         return r;
265         } else {
266                 r = manager_get_session_by_pid(m, pid, &session);
267                 if (r < 0)
268                         return r;
269
270                 if (!session)
271                         return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
272         }
273
274         p = session_bus_path(session);
275         if (!p)
276                 return -ENOMEM;
277
278         return sd_bus_reply_method_return(message, "o", p);
279 }
280
281 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
282         _cleanup_free_ char *p = NULL;
283         Manager *m = userdata;
284         uint32_t uid;
285         User *user;
286         int r;
287
288         assert(bus);
289         assert(message);
290         assert(m);
291
292         r = sd_bus_message_read(message, "u", &uid);
293         if (r < 0)
294                 return r;
295
296         r = manager_get_user_from_creds(m, message, uid, error, &user);
297         if (r < 0)
298                 return r;
299
300         p = user_bus_path(user);
301         if (!p)
302                 return -ENOMEM;
303
304         return sd_bus_reply_method_return(message, "o", p);
305 }
306
307 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
308         _cleanup_free_ char *p = NULL;
309         Manager *m = userdata;
310         User *user = NULL;
311         pid_t pid;
312         int r;
313
314         assert(bus);
315         assert(message);
316         assert(m);
317
318         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
319
320         r = sd_bus_message_read(message, "u", &pid);
321         if (r < 0)
322                 return r;
323
324         if (pid <= 0) {
325                 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
326                 if (r < 0)
327                         return r;
328         } else {
329                 r = manager_get_user_by_pid(m, pid, &user);
330                 if (r < 0)
331                         return r;
332                 if (!user)
333                         return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
334         }
335
336         p = user_bus_path(user);
337         if (!p)
338                 return -ENOMEM;
339
340         return sd_bus_reply_method_return(message, "o", p);
341 }
342
343 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
344         _cleanup_free_ char *p = NULL;
345         Manager *m = userdata;
346         const char *name;
347         Seat *seat;
348         int r;
349
350         assert(bus);
351         assert(message);
352         assert(m);
353
354         r = sd_bus_message_read(message, "s", &name);
355         if (r < 0)
356                 return r;
357
358         r = manager_get_seat_from_creds(m, message, name, error, &seat);
359         if (r < 0)
360                 return r;
361
362         p = seat_bus_path(seat);
363         if (!p)
364                 return -ENOMEM;
365
366         return sd_bus_reply_method_return(message, "o", p);
367 }
368
369 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
370         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
371         Manager *m = userdata;
372         Session *session;
373         Iterator i;
374         int r;
375
376         assert(bus);
377         assert(message);
378         assert(m);
379
380         r = sd_bus_message_new_method_return(message, &reply);
381         if (r < 0)
382                 return r;
383
384         r = sd_bus_message_open_container(reply, 'a', "(susso)");
385         if (r < 0)
386                 return r;
387
388         HASHMAP_FOREACH(session, m->sessions, i) {
389                 _cleanup_free_ char *p = NULL;
390
391                 p = session_bus_path(session);
392                 if (!p)
393                         return -ENOMEM;
394
395                 r = sd_bus_message_append(reply, "(susso)",
396                                           session->id,
397                                           (uint32_t) session->user->uid,
398                                           session->user->name,
399                                           session->seat ? session->seat->id : "",
400                                           p);
401                 if (r < 0)
402                         return r;
403         }
404
405         r = sd_bus_message_close_container(reply);
406         if (r < 0)
407                 return r;
408
409         return sd_bus_send(bus, reply, NULL);
410 }
411
412 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
413         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
414         Manager *m = userdata;
415         User *user;
416         Iterator i;
417         int r;
418
419         assert(bus);
420         assert(message);
421         assert(m);
422
423         r = sd_bus_message_new_method_return(message, &reply);
424         if (r < 0)
425                 return r;
426
427         r = sd_bus_message_open_container(reply, 'a', "(uso)");
428         if (r < 0)
429                 return r;
430
431         HASHMAP_FOREACH(user, m->users, i) {
432                 _cleanup_free_ char *p = NULL;
433
434                 p = user_bus_path(user);
435                 if (!p)
436                         return -ENOMEM;
437
438                 r = sd_bus_message_append(reply, "(uso)",
439                                           (uint32_t) user->uid,
440                                           user->name,
441                                           p);
442                 if (r < 0)
443                         return r;
444         }
445
446         r = sd_bus_message_close_container(reply);
447         if (r < 0)
448                 return r;
449
450         return sd_bus_send(bus, reply, NULL);
451 }
452
453 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
454         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
455         Manager *m = userdata;
456         Seat *seat;
457         Iterator i;
458         int r;
459
460         assert(bus);
461         assert(message);
462         assert(m);
463
464         r = sd_bus_message_new_method_return(message, &reply);
465         if (r < 0)
466                 return r;
467
468         r = sd_bus_message_open_container(reply, 'a', "(so)");
469         if (r < 0)
470                 return r;
471
472         HASHMAP_FOREACH(seat, m->seats, i) {
473                 _cleanup_free_ char *p = NULL;
474
475                 p = seat_bus_path(seat);
476                 if (!p)
477                         return -ENOMEM;
478
479                 r = sd_bus_message_append(reply, "(so)", seat->id, p);
480                 if (r < 0)
481                         return r;
482         }
483
484         r = sd_bus_message_close_container(reply);
485         if (r < 0)
486                 return r;
487
488         return sd_bus_send(bus, reply, NULL);
489 }
490
491 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
492         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
493         Manager *m = userdata;
494         Inhibitor *inhibitor;
495         Iterator i;
496         int r;
497
498         r = sd_bus_message_new_method_return(message, &reply);
499         if (r < 0)
500                 return r;
501
502         r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
503         if (r < 0)
504                 return r;
505
506         HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
507
508                 r = sd_bus_message_append(reply, "(ssssuu)",
509                                           strempty(inhibit_what_to_string(inhibitor->what)),
510                                           strempty(inhibitor->who),
511                                           strempty(inhibitor->why),
512                                           strempty(inhibit_mode_to_string(inhibitor->mode)),
513                                           (uint32_t) inhibitor->uid,
514                                           (uint32_t) inhibitor->pid);
515                 if (r < 0)
516                         return r;
517         }
518
519         r = sd_bus_message_close_container(reply);
520         if (r < 0)
521                 return r;
522
523         return sd_bus_send(bus, reply, NULL);
524 }
525
526 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
527         const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
528         uint32_t uid, leader, audit_id = 0;
529         _cleanup_free_ char *id = NULL;
530         Session *session = NULL;
531         Manager *m = userdata;
532         User *user = NULL;
533         Seat *seat = NULL;
534         int remote;
535         uint32_t vtnr = 0;
536         SessionType t;
537         SessionClass c;
538         int r;
539
540         assert(bus);
541         assert(message);
542         assert(m);
543
544         r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
545         if (r < 0)
546                 return r;
547
548         if (leader == 1)
549                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
550
551         if (isempty(type))
552                 t = _SESSION_TYPE_INVALID;
553         else {
554                 t = session_type_from_string(type);
555                 if (t < 0)
556                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
557         }
558
559         if (isempty(class))
560                 c = _SESSION_CLASS_INVALID;
561         else {
562                 c = session_class_from_string(class);
563                 if (c < 0)
564                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
565         }
566
567         if (isempty(desktop))
568                 desktop = NULL;
569         else {
570                 if (!string_is_safe(desktop))
571                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
572         }
573
574         if (isempty(cseat))
575                 seat = NULL;
576         else {
577                 seat = hashmap_get(m->seats, cseat);
578                 if (!seat)
579                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
580         }
581
582         if (tty_is_vc(tty)) {
583                 int v;
584
585                 if (!seat)
586                         seat = m->seat0;
587                 else if (seat != m->seat0)
588                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
589
590                 v = vtnr_from_tty(tty);
591                 if (v <= 0)
592                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
593
594                 if (!vtnr)
595                         vtnr = (uint32_t) v;
596                 else if (vtnr != (uint32_t) v)
597                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
598
599         } else if (tty_is_console(tty)) {
600
601                 if (!seat)
602                         seat = m->seat0;
603                 else if (seat != m->seat0)
604                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
605
606                 if (vtnr != 0)
607                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
608         }
609
610         if (seat) {
611                 if (seat_has_vts(seat)) {
612                         if (!vtnr || vtnr > 63)
613                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
614                 } else {
615                         if (vtnr != 0)
616                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
617                 }
618         }
619
620         r = sd_bus_message_enter_container(message, 'a', "(sv)");
621         if (r < 0)
622                 return r;
623
624         if (t == _SESSION_TYPE_INVALID) {
625                 if (!isempty(display))
626                         t = SESSION_X11;
627                 else if (!isempty(tty))
628                         t = SESSION_TTY;
629                 else
630                         t = SESSION_UNSPECIFIED;
631         }
632
633         if (c == _SESSION_CLASS_INVALID) {
634                 if (t == SESSION_UNSPECIFIED)
635                         c = SESSION_BACKGROUND;
636                 else
637                         c = SESSION_USER;
638         }
639
640         if (leader <= 0) {
641                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
642
643                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
644                 if (r < 0)
645                         return r;
646
647                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
648                 if (r < 0)
649                         return r;
650         }
651
652         manager_get_session_by_pid(m, leader, &session);
653         if (session) {
654                 _cleanup_free_ char *path = NULL;
655                 _cleanup_close_ int fifo_fd = -1;
656
657                 /* Session already exists, client is probably
658                  * something like "su" which changes uid but is still
659                  * the same session */
660
661                 fifo_fd = session_create_fifo(session);
662                 if (fifo_fd < 0)
663                         return fifo_fd;
664
665                 path = session_bus_path(session);
666                 if (!path)
667                         return -ENOMEM;
668
669                 log_debug("Sending reply about an existing session: "
670                           "id=%s object_path=%s uid=%u runtime_path=%s "
671                           "session_fd=%d seat=%s vtnr=%u",
672                           session->id,
673                           path,
674                           (uint32_t) session->user->uid,
675                           session->user->runtime_path,
676                           fifo_fd,
677                           session->seat ? session->seat->id : "",
678                           (uint32_t) session->vtnr);
679
680                 return sd_bus_reply_method_return(
681                                 message, "soshusub",
682                                 session->id,
683                                 path,
684                                 session->user->runtime_path,
685                                 fifo_fd,
686                                 (uint32_t) session->user->uid,
687                                 session->seat ? session->seat->id : "",
688                                 (uint32_t) session->vtnr,
689                                 true);
690         }
691
692         audit_session_from_pid(leader, &audit_id);
693         if (audit_id > 0) {
694                 /* Keep our session IDs and the audit session IDs in sync */
695
696                 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
697                         return -ENOMEM;
698
699                 /* Wut? There's already a session by this name and we
700                  * didn't find it above? Weird, then let's not trust
701                  * the audit data and let's better register a new
702                  * ID */
703                 if (hashmap_get(m->sessions, id)) {
704                         log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
705                         audit_id = 0;
706
707                         free(id);
708                         id = NULL;
709                 }
710         }
711
712         if (!id) {
713                 do {
714                         free(id);
715                         id = NULL;
716
717                         if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
718                                 return -ENOMEM;
719
720                 } while (hashmap_get(m->sessions, id));
721         }
722
723         r = manager_add_user_by_uid(m, uid, &user);
724         if (r < 0)
725                 goto fail;
726
727         r = manager_add_session(m, id, &session);
728         if (r < 0)
729                 goto fail;
730
731         session_set_user(session, user);
732
733         session->leader = leader;
734         session->audit_id = audit_id;
735         session->type = t;
736         session->class = c;
737         session->remote = remote;
738         session->vtnr = vtnr;
739
740         if (!isempty(tty)) {
741                 session->tty = strdup(tty);
742                 if (!session->tty) {
743                         r = -ENOMEM;
744                         goto fail;
745                 }
746         }
747
748         if (!isempty(display)) {
749                 session->display = strdup(display);
750                 if (!session->display) {
751                         r = -ENOMEM;
752                         goto fail;
753                 }
754         }
755
756         if (!isempty(remote_user)) {
757                 session->remote_user = strdup(remote_user);
758                 if (!session->remote_user) {
759                         r = -ENOMEM;
760                         goto fail;
761                 }
762         }
763
764         if (!isempty(remote_host)) {
765                 session->remote_host = strdup(remote_host);
766                 if (!session->remote_host) {
767                         r = -ENOMEM;
768                         goto fail;
769                 }
770         }
771
772         if (!isempty(service)) {
773                 session->service = strdup(service);
774                 if (!session->service) {
775                         r = -ENOMEM;
776                         goto fail;
777                 }
778         }
779
780         if (!isempty(desktop)) {
781                 session->desktop = strdup(desktop);
782                 if (!session->desktop) {
783                         r = -ENOMEM;
784                         goto fail;
785                 }
786         }
787
788         if (seat) {
789                 r = seat_attach_session(seat, session);
790                 if (r < 0)
791                         goto fail;
792         }
793
794         r = session_start(session);
795         if (r < 0)
796                 goto fail;
797
798         session->create_message = sd_bus_message_ref(message);
799
800         /* Now, let's wait until the slice unit and stuff got
801          * created. We send the reply back from
802          * session_send_create_reply(). */
803
804         return 1;
805
806 fail:
807         if (session)
808                 session_add_to_gc_queue(session);
809
810         if (user)
811                 user_add_to_gc_queue(user);
812
813         return r;
814 }
815
816 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
817         Manager *m = userdata;
818         Session *session;
819         const char *name;
820         int r;
821
822         assert(bus);
823         assert(message);
824         assert(m);
825
826         r = sd_bus_message_read(message, "s", &name);
827         if (r < 0)
828                 return r;
829
830         r = manager_get_session_from_creds(m, message, name, error, &session);
831         if (r < 0)
832                 return r;
833
834         session_release(session);
835
836         return sd_bus_reply_method_return(message, NULL);
837 }
838
839 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
840         Manager *m = userdata;
841         Session *session;
842         const char *name;
843         int r;
844
845         assert(bus);
846         assert(message);
847         assert(m);
848
849         r = sd_bus_message_read(message, "s", &name);
850         if (r < 0)
851                 return r;
852
853         r = manager_get_session_from_creds(m, message, name, error, &session);
854         if (r < 0)
855                 return r;
856
857         return bus_session_method_activate(bus, message, session, error);
858 }
859
860 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
861         const char *session_name, *seat_name;
862         Manager *m = userdata;
863         Session *session;
864         Seat *seat;
865         int r;
866
867         assert(bus);
868         assert(message);
869         assert(m);
870
871         /* Same as ActivateSession() but refuses to work if
872          * the seat doesn't match */
873
874         r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
875         if (r < 0)
876                 return r;
877
878         r = manager_get_session_from_creds(m, message, session_name, error, &session);
879         if (r < 0)
880                 return r;
881
882         r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
883         if (r < 0)
884                 return r;
885
886         if (session->seat != seat)
887                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
888
889         r = session_activate(session);
890         if (r < 0)
891                 return r;
892
893         return sd_bus_reply_method_return(message, NULL);
894 }
895
896 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
897         Manager *m = userdata;
898         Session *session;
899         const char *name;
900         int r;
901
902         assert(bus);
903         assert(message);
904         assert(m);
905
906         r = sd_bus_message_read(message, "s", &name);
907         if (r < 0)
908                 return r;
909
910         r = manager_get_session_from_creds(m, message, name, error, &session);
911         if (r < 0)
912                 return r;
913
914         return bus_session_method_lock(bus, message, session, error);
915 }
916
917 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
918         Manager *m = userdata;
919         int r;
920
921         assert(bus);
922         assert(message);
923         assert(m);
924
925         r = bus_verify_polkit_async(
926                         message,
927                         CAP_SYS_ADMIN,
928                         "org.freedesktop.login1.lock-sessions",
929                         false,
930                         UID_INVALID,
931                         &m->polkit_registry,
932                         error);
933         if (r < 0)
934                 return r;
935         if (r == 0)
936                 return 1; /* Will call us back */
937
938         r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
939         if (r < 0)
940                 return r;
941
942         return sd_bus_reply_method_return(message, NULL);
943 }
944
945 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
946         const char *name;
947         Manager *m = userdata;
948         Session *session;
949         int r;
950
951         assert(bus);
952         assert(message);
953         assert(m);
954
955         r = sd_bus_message_read(message, "s", &name);
956         if (r < 0)
957                 return r;
958
959         r = manager_get_session_from_creds(m, message, name, error, &session);
960         if (r < 0)
961                 return r;
962
963         return bus_session_method_kill(bus, message, session, error);
964 }
965
966 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
967         Manager *m = userdata;
968         uint32_t uid;
969         User *user;
970         int r;
971
972         assert(bus);
973         assert(message);
974         assert(m);
975
976         r = sd_bus_message_read(message, "u", &uid);
977         if (r < 0)
978                 return r;
979
980         r = manager_get_user_from_creds(m, message, uid, error, &user);
981         if (r < 0)
982                 return r;
983
984         return bus_user_method_kill(bus, message, user, error);
985 }
986
987 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
988         Manager *m = userdata;
989         const char *name;
990         Session *session;
991         int r;
992
993         assert(bus);
994         assert(message);
995         assert(m);
996
997         r = sd_bus_message_read(message, "s", &name);
998         if (r < 0)
999                 return r;
1000
1001         r = manager_get_session_from_creds(m, message, name, error, &session);
1002         if (r < 0)
1003                 return r;
1004
1005         return bus_session_method_terminate(bus, message, session, error);
1006 }
1007
1008 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1009         Manager *m = userdata;
1010         uint32_t uid;
1011         User *user;
1012         int r;
1013
1014         assert(bus);
1015         assert(message);
1016         assert(m);
1017
1018         r = sd_bus_message_read(message, "u", &uid);
1019         if (r < 0)
1020                 return r;
1021
1022         r = manager_get_user_from_creds(m, message, uid, error, &user);
1023         if (r < 0)
1024                 return r;
1025
1026         return bus_user_method_terminate(bus, message, user, error);
1027 }
1028
1029 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1030         Manager *m = userdata;
1031         const char *name;
1032         Seat *seat;
1033         int r;
1034
1035         assert(bus);
1036         assert(message);
1037         assert(m);
1038
1039         r = sd_bus_message_read(message, "s", &name);
1040         if (r < 0)
1041                 return r;
1042
1043         r = manager_get_seat_from_creds(m, message, name, error, &seat);
1044         if (r < 0)
1045                 return r;
1046
1047         return bus_seat_method_terminate(bus, message, seat, error);
1048 }
1049
1050 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1051         _cleanup_free_ char *cc = NULL;
1052         Manager *m = userdata;
1053         int b, r;
1054         struct passwd *pw;
1055         const char *path;
1056         uint32_t uid;
1057         int interactive;
1058
1059         assert(bus);
1060         assert(message);
1061         assert(m);
1062
1063         r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1064         if (r < 0)
1065                 return r;
1066
1067         if (uid == UID_INVALID) {
1068                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1069
1070                 /* Note that we get the owner UID of the session, not the actual client UID here! */
1071                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1072                 if (r < 0)
1073                         return r;
1074
1075                 r = sd_bus_creds_get_owner_uid(creds, &uid);
1076                 if (r < 0)
1077                         return r;
1078         }
1079
1080         errno = 0;
1081         pw = getpwuid(uid);
1082         if (!pw)
1083                 return errno ? -errno : -ENOENT;
1084
1085         r = bus_verify_polkit_async(
1086                         message,
1087                         CAP_SYS_ADMIN,
1088                         "org.freedesktop.login1.set-user-linger",
1089                         interactive,
1090                         UID_INVALID,
1091                         &m->polkit_registry,
1092                         error);
1093         if (r < 0)
1094                 return r;
1095         if (r == 0)
1096                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1097
1098         mkdir_p_label("/var/lib/systemd", 0755);
1099
1100         r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1101         if (r < 0)
1102                 return r;
1103
1104         cc = cescape(pw->pw_name);
1105         if (!cc)
1106                 return -ENOMEM;
1107
1108         path = strjoina("/var/lib/systemd/linger/", cc);
1109         if (b) {
1110                 User *u;
1111
1112                 r = touch(path);
1113                 if (r < 0)
1114                         return r;
1115
1116                 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1117                         user_start(u);
1118
1119         } else {
1120                 User *u;
1121
1122                 r = unlink(path);
1123                 if (r < 0 && errno != ENOENT)
1124                         return -errno;
1125
1126                 u = hashmap_get(m->users, UID_TO_PTR(uid));
1127                 if (u)
1128                         user_add_to_gc_queue(u);
1129         }
1130
1131         return sd_bus_reply_method_return(message, NULL);
1132 }
1133
1134 static int trigger_device(Manager *m, struct udev_device *d) {
1135         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1136         struct udev_list_entry *first, *item;
1137         int r;
1138
1139         assert(m);
1140
1141         e = udev_enumerate_new(m->udev);
1142         if (!e)
1143                 return -ENOMEM;
1144
1145         if (d) {
1146                 r = udev_enumerate_add_match_parent(e, d);
1147                 if (r < 0)
1148                         return r;
1149         }
1150
1151         r = udev_enumerate_scan_devices(e);
1152         if (r < 0)
1153                 return r;
1154
1155         first = udev_enumerate_get_list_entry(e);
1156         udev_list_entry_foreach(item, first) {
1157                 _cleanup_free_ char *t = NULL;
1158                 const char *p;
1159
1160                 p = udev_list_entry_get_name(item);
1161
1162                 t = strappend(p, "/uevent");
1163                 if (!t)
1164                         return -ENOMEM;
1165
1166                 write_string_file(t, "change");
1167         }
1168
1169         return 0;
1170 }
1171
1172 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1173         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1174         _cleanup_free_ char *rule = NULL, *file = NULL;
1175         const char *id_for_seat;
1176         int r;
1177
1178         assert(m);
1179         assert(seat);
1180         assert(sysfs);
1181
1182         d = udev_device_new_from_syspath(m->udev, sysfs);
1183         if (!d)
1184                 return -ENODEV;
1185
1186         if (!udev_device_has_tag(d, "seat"))
1187                 return -ENODEV;
1188
1189         id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1190         if (!id_for_seat)
1191                 return -ENODEV;
1192
1193         if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1194                 return -ENOMEM;
1195
1196         if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1197                 return -ENOMEM;
1198
1199         mkdir_p_label("/etc/udev/rules.d", 0755);
1200         mac_selinux_init("/etc");
1201         r = write_string_file_atomic_label(file, rule);
1202         if (r < 0)
1203                 return r;
1204
1205         return trigger_device(m, d);
1206 }
1207
1208 static int flush_devices(Manager *m) {
1209         _cleanup_closedir_ DIR *d;
1210
1211         assert(m);
1212
1213         d = opendir("/etc/udev/rules.d");
1214         if (!d) {
1215                 if (errno != ENOENT)
1216                         log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1217         } else {
1218                 struct dirent *de;
1219
1220                 while ((de = readdir(d))) {
1221
1222                         if (!dirent_is_file(de))
1223                                 continue;
1224
1225                         if (!startswith(de->d_name, "72-seat-"))
1226                                 continue;
1227
1228                         if (!endswith(de->d_name, ".rules"))
1229                                 continue;
1230
1231                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1232                                 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1233                 }
1234         }
1235
1236         return trigger_device(m, NULL);
1237 }
1238
1239 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1240         const char *sysfs, *seat;
1241         Manager *m = userdata;
1242         int interactive, r;
1243
1244         assert(bus);
1245         assert(message);
1246         assert(m);
1247
1248         r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1249         if (r < 0)
1250                 return r;
1251
1252         if (!path_startswith(sysfs, "/sys"))
1253                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1254
1255         if (!seat_name_is_valid(seat))
1256                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1257
1258         r = bus_verify_polkit_async(
1259                         message,
1260                         CAP_SYS_ADMIN,
1261                         "org.freedesktop.login1.attach-device",
1262                         interactive,
1263                         UID_INVALID,
1264                         &m->polkit_registry,
1265                         error);
1266         if (r < 0)
1267                 return r;
1268         if (r == 0)
1269                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1270
1271         r = attach_device(m, seat, sysfs);
1272         if (r < 0)
1273                 return r;
1274
1275         return sd_bus_reply_method_return(message, NULL);
1276 }
1277
1278 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1279         Manager *m = userdata;
1280         int interactive, r;
1281
1282         assert(bus);
1283         assert(message);
1284         assert(m);
1285
1286         r = sd_bus_message_read(message, "b", &interactive);
1287         if (r < 0)
1288                 return r;
1289
1290         r = bus_verify_polkit_async(
1291                         message,
1292                         CAP_SYS_ADMIN,
1293                         "org.freedesktop.login1.flush-devices",
1294                         interactive,
1295                         UID_INVALID,
1296                         &m->polkit_registry,
1297                         error);
1298         if (r < 0)
1299                 return r;
1300         if (r == 0)
1301                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1302
1303         r = flush_devices(m);
1304         if (r < 0)
1305                 return r;
1306
1307         return sd_bus_reply_method_return(message, NULL);
1308 }
1309
1310 static int have_multiple_sessions(
1311                 Manager *m,
1312                 uid_t uid) {
1313
1314         Session *session;
1315         Iterator i;
1316
1317         assert(m);
1318
1319         /* Check for other users' sessions. Greeter sessions do not
1320          * count, and non-login sessions do not count either. */
1321         HASHMAP_FOREACH(session, m->sessions, i)
1322                 if (session->class == SESSION_USER &&
1323                     session->user->uid != uid)
1324                         return true;
1325
1326         return false;
1327 }
1328
1329 static int bus_manager_log_shutdown(
1330                 Manager *m,
1331                 InhibitWhat w,
1332                 const char *unit_name) {
1333
1334         const char *p, *q;
1335
1336         assert(m);
1337         assert(unit_name);
1338
1339         if (w != INHIBIT_SHUTDOWN)
1340                 return 0;
1341
1342         if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1343                 p = "MESSAGE=System is powering down.";
1344                 q = "SHUTDOWN=power-off";
1345         } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1346                 p = "MESSAGE=System is halting.";
1347                 q = "SHUTDOWN=halt";
1348         } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1349                 p = "MESSAGE=System is rebooting.";
1350                 q = "SHUTDOWN=reboot";
1351         } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1352                 p = "MESSAGE=System is rebooting with kexec.";
1353                 q = "SHUTDOWN=kexec";
1354         } else {
1355                 p = "MESSAGE=System is shutting down.";
1356                 q = NULL;
1357         }
1358
1359         return log_struct(LOG_NOTICE,
1360                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1361                           p,
1362                           q,
1363                           NULL);
1364 }
1365
1366 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1367         Manager *m = userdata;
1368
1369         assert(e);
1370         assert(m);
1371
1372         m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1373         return 0;
1374 }
1375
1376 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1377         int r;
1378
1379         assert(m);
1380
1381         if (until <= now(CLOCK_MONOTONIC))
1382                 return 0;
1383
1384         /* We want to ignore the lid switch for a while after each
1385          * suspend, and after boot-up. Hence let's install a timer for
1386          * this. As long as the event source exists we ignore the lid
1387          * switch. */
1388
1389         if (m->lid_switch_ignore_event_source) {
1390                 usec_t u;
1391
1392                 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1393                 if (r < 0)
1394                         return r;
1395
1396                 if (until <= u)
1397                         return 0;
1398
1399                 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1400         } else
1401                 r = sd_event_add_time(
1402                                 m->event,
1403                                 &m->lid_switch_ignore_event_source,
1404                                 CLOCK_MONOTONIC,
1405                                 until, 0,
1406                                 lid_switch_ignore_handler, m);
1407
1408         return r;
1409 }
1410
1411 static int execute_shutdown_or_sleep(
1412                 Manager *m,
1413                 InhibitWhat w,
1414                 const char *unit_name,
1415                 sd_bus_error *error) {
1416
1417         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1418         const char *p;
1419         char *c;
1420         int r;
1421
1422         assert(m);
1423         assert(w >= 0);
1424         assert(w < _INHIBIT_WHAT_MAX);
1425         assert(unit_name);
1426
1427         bus_manager_log_shutdown(m, w, unit_name);
1428
1429         r = sd_bus_call_method(
1430                         m->bus,
1431                         "org.freedesktop.systemd1",
1432                         "/org/freedesktop/systemd1",
1433                         "org.freedesktop.systemd1.Manager",
1434                         "StartUnit",
1435                         error,
1436                         &reply,
1437                         "ss", unit_name, "replace-irreversibly");
1438         if (r < 0)
1439                 return r;
1440
1441         r = sd_bus_message_read(reply, "o", &p);
1442         if (r < 0)
1443                 return r;
1444
1445         c = strdup(p);
1446         if (!c)
1447                 return -ENOMEM;
1448
1449         m->action_unit = unit_name;
1450         free(m->action_job);
1451         m->action_job = c;
1452         m->action_what = w;
1453
1454         /* Make sure the lid switch is ignored for a while */
1455         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + IGNORE_LID_SWITCH_SUSPEND_USEC);
1456
1457         return 0;
1458 }
1459
1460 static int delay_shutdown_or_sleep(
1461                 Manager *m,
1462                 InhibitWhat w,
1463                 const char *unit_name) {
1464
1465         assert(m);
1466         assert(w >= 0);
1467         assert(w < _INHIBIT_WHAT_MAX);
1468         assert(unit_name);
1469
1470         m->action_timestamp = now(CLOCK_MONOTONIC);
1471         m->action_unit = unit_name;
1472         m->action_what = w;
1473
1474         return 0;
1475 }
1476
1477 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1478
1479         static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1480                 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1481                 [INHIBIT_SLEEP] = "PrepareForSleep"
1482         };
1483
1484         int active = _active;
1485
1486         assert(m);
1487         assert(w >= 0);
1488         assert(w < _INHIBIT_WHAT_MAX);
1489         assert(signal_name[w]);
1490
1491         return sd_bus_emit_signal(m->bus,
1492                                   "/org/freedesktop/login1",
1493                                   "org.freedesktop.login1.Manager",
1494                                   signal_name[w],
1495                                   "b",
1496                                   active);
1497 }
1498
1499 int bus_manager_shutdown_or_sleep_now_or_later(
1500                 Manager *m,
1501                 const char *unit_name,
1502                 InhibitWhat w,
1503                 sd_bus_error *error) {
1504
1505         bool delayed;
1506         int r;
1507
1508         assert(m);
1509         assert(unit_name);
1510         assert(w >= 0);
1511         assert(w <= _INHIBIT_WHAT_MAX);
1512         assert(!m->action_job);
1513
1514         /* Tell everybody to prepare for shutdown/sleep */
1515         send_prepare_for(m, w, true);
1516
1517         delayed =
1518                 m->inhibit_delay_max > 0 &&
1519                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1520
1521         if (delayed)
1522                 /* Shutdown is delayed, keep in mind what we
1523                  * want to do, and start a timeout */
1524                 r = delay_shutdown_or_sleep(m, w, unit_name);
1525         else
1526                 /* Shutdown is not delayed, execute it
1527                  * immediately */
1528                 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1529
1530         return r;
1531 }
1532
1533 static int method_do_shutdown_or_sleep(
1534                 Manager *m,
1535                 sd_bus_message *message,
1536                 const char *unit_name,
1537                 InhibitWhat w,
1538                 const char *action,
1539                 const char *action_multiple_sessions,
1540                 const char *action_ignore_inhibit,
1541                 const char *sleep_verb,
1542                 sd_bus_message_handler_t method,
1543                 sd_bus_error *error) {
1544
1545         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1546         bool multiple_sessions, blocked;
1547         int interactive, r;
1548         uid_t uid;
1549
1550         assert(m);
1551         assert(message);
1552         assert(unit_name);
1553         assert(w >= 0);
1554         assert(w <= _INHIBIT_WHAT_MAX);
1555         assert(action);
1556         assert(action_multiple_sessions);
1557         assert(action_ignore_inhibit);
1558         assert(method);
1559
1560         r = sd_bus_message_read(message, "b", &interactive);
1561         if (r < 0)
1562                 return r;
1563
1564         /* Don't allow multiple jobs being executed at the same time */
1565         if (m->action_what)
1566                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1567
1568         if (sleep_verb) {
1569                 r = can_sleep(sleep_verb);
1570                 if (r < 0)
1571                         return r;
1572
1573                 if (r == 0)
1574                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1575         }
1576
1577         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1578         if (r < 0)
1579                 return r;
1580
1581         r = sd_bus_creds_get_euid(creds, &uid);
1582         if (r < 0)
1583                 return r;
1584
1585         r = have_multiple_sessions(m, uid);
1586         if (r < 0)
1587                 return r;
1588
1589         multiple_sessions = r > 0;
1590         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1591
1592         if (multiple_sessions) {
1593                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1594                 if (r < 0)
1595                         return r;
1596                 if (r == 0)
1597                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1598         }
1599
1600         if (blocked) {
1601                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1602                 if (r < 0)
1603                         return r;
1604                 if (r == 0)
1605                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1606         }
1607
1608         if (!multiple_sessions && !blocked) {
1609                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1610                 if (r < 0)
1611                         return r;
1612                 if (r == 0)
1613                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1614         }
1615
1616         r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1617         if (r < 0)
1618                 return r;
1619
1620         return sd_bus_reply_method_return(message, NULL);
1621 }
1622
1623 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1624         Manager *m = userdata;
1625
1626         return method_do_shutdown_or_sleep(
1627                         m, message,
1628                         SPECIAL_POWEROFF_TARGET,
1629                         INHIBIT_SHUTDOWN,
1630                         "org.freedesktop.login1.power-off",
1631                         "org.freedesktop.login1.power-off-multiple-sessions",
1632                         "org.freedesktop.login1.power-off-ignore-inhibit",
1633                         NULL,
1634                         method_poweroff,
1635                         error);
1636 }
1637
1638 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1639         Manager *m = userdata;
1640
1641         return method_do_shutdown_or_sleep(
1642                         m, message,
1643                         SPECIAL_REBOOT_TARGET,
1644                         INHIBIT_SHUTDOWN,
1645                         "org.freedesktop.login1.reboot",
1646                         "org.freedesktop.login1.reboot-multiple-sessions",
1647                         "org.freedesktop.login1.reboot-ignore-inhibit",
1648                         NULL,
1649                         method_reboot,
1650                         error);
1651 }
1652
1653 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1654         Manager *m = userdata;
1655
1656         return method_do_shutdown_or_sleep(
1657                         m, message,
1658                         SPECIAL_SUSPEND_TARGET,
1659                         INHIBIT_SLEEP,
1660                         "org.freedesktop.login1.suspend",
1661                         "org.freedesktop.login1.suspend-multiple-sessions",
1662                         "org.freedesktop.login1.suspend-ignore-inhibit",
1663                         "suspend",
1664                         method_suspend,
1665                         error);
1666 }
1667
1668 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1669         Manager *m = userdata;
1670
1671         return method_do_shutdown_or_sleep(
1672                         m, message,
1673                         SPECIAL_HIBERNATE_TARGET,
1674                         INHIBIT_SLEEP,
1675                         "org.freedesktop.login1.hibernate",
1676                         "org.freedesktop.login1.hibernate-multiple-sessions",
1677                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1678                         "hibernate",
1679                         method_hibernate,
1680                         error);
1681 }
1682
1683 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1684         Manager *m = userdata;
1685
1686         return method_do_shutdown_or_sleep(
1687                         m, message,
1688                         SPECIAL_HYBRID_SLEEP_TARGET,
1689                         INHIBIT_SLEEP,
1690                         "org.freedesktop.login1.hibernate",
1691                         "org.freedesktop.login1.hibernate-multiple-sessions",
1692                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1693                         "hybrid-sleep",
1694                         method_hybrid_sleep,
1695                         error);
1696 }
1697
1698 static int method_can_shutdown_or_sleep(
1699                 Manager *m,
1700                 sd_bus_message *message,
1701                 InhibitWhat w,
1702                 const char *action,
1703                 const char *action_multiple_sessions,
1704                 const char *action_ignore_inhibit,
1705                 const char *sleep_verb,
1706                 sd_bus_error *error) {
1707
1708         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1709         bool multiple_sessions, challenge, blocked;
1710         const char *result = NULL;
1711         uid_t uid;
1712         int r;
1713
1714         assert(m);
1715         assert(message);
1716         assert(w >= 0);
1717         assert(w <= _INHIBIT_WHAT_MAX);
1718         assert(action);
1719         assert(action_multiple_sessions);
1720         assert(action_ignore_inhibit);
1721
1722         if (sleep_verb) {
1723                 r = can_sleep(sleep_verb);
1724                 if (r < 0)
1725                         return r;
1726                 if (r == 0)
1727                         return sd_bus_reply_method_return(message, "s", "na");
1728         }
1729
1730         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1731         if (r < 0)
1732                 return r;
1733
1734         r = sd_bus_creds_get_euid(creds, &uid);
1735         if (r < 0)
1736                 return r;
1737
1738         r = have_multiple_sessions(m, uid);
1739         if (r < 0)
1740                 return r;
1741
1742         multiple_sessions = r > 0;
1743         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1744
1745         if (multiple_sessions) {
1746                 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error);
1747                 if (r < 0)
1748                         return r;
1749
1750                 if (r > 0)
1751                         result = "yes";
1752                 else if (challenge)
1753                         result = "challenge";
1754                 else
1755                         result = "no";
1756         }
1757
1758         if (blocked) {
1759                 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error);
1760                 if (r < 0)
1761                         return r;
1762
1763                 if (r > 0 && !result)
1764                         result = "yes";
1765                 else if (challenge && (!result || streq(result, "yes")))
1766                         result = "challenge";
1767                 else
1768                         result = "no";
1769         }
1770
1771         if (!multiple_sessions && !blocked) {
1772                 /* If neither inhibit nor multiple sessions
1773                  * apply then just check the normal policy */
1774
1775                 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error);
1776                 if (r < 0)
1777                         return r;
1778
1779                 if (r > 0)
1780                         result = "yes";
1781                 else if (challenge)
1782                         result = "challenge";
1783                 else
1784                         result = "no";
1785         }
1786
1787         return sd_bus_reply_method_return(message, "s", result);
1788 }
1789
1790 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1791         Manager *m = userdata;
1792
1793         return method_can_shutdown_or_sleep(
1794                         m, message,
1795                         INHIBIT_SHUTDOWN,
1796                         "org.freedesktop.login1.power-off",
1797                         "org.freedesktop.login1.power-off-multiple-sessions",
1798                         "org.freedesktop.login1.power-off-ignore-inhibit",
1799                         NULL,
1800                         error);
1801 }
1802
1803 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1804         Manager *m = userdata;
1805
1806         return method_can_shutdown_or_sleep(
1807                         m, message,
1808                         INHIBIT_SHUTDOWN,
1809                         "org.freedesktop.login1.reboot",
1810                         "org.freedesktop.login1.reboot-multiple-sessions",
1811                         "org.freedesktop.login1.reboot-ignore-inhibit",
1812                         NULL,
1813                         error);
1814 }
1815
1816 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1817         Manager *m = userdata;
1818
1819         return method_can_shutdown_or_sleep(
1820                         m, message,
1821                         INHIBIT_SLEEP,
1822                         "org.freedesktop.login1.suspend",
1823                         "org.freedesktop.login1.suspend-multiple-sessions",
1824                         "org.freedesktop.login1.suspend-ignore-inhibit",
1825                         "suspend",
1826                         error);
1827 }
1828
1829 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1830         Manager *m = userdata;
1831
1832         return method_can_shutdown_or_sleep(
1833                         m, message,
1834                         INHIBIT_SLEEP,
1835                         "org.freedesktop.login1.hibernate",
1836                         "org.freedesktop.login1.hibernate-multiple-sessions",
1837                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1838                         "hibernate",
1839                         error);
1840 }
1841
1842 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1843         Manager *m = userdata;
1844
1845         return method_can_shutdown_or_sleep(
1846                         m, message,
1847                         INHIBIT_SLEEP,
1848                         "org.freedesktop.login1.hibernate",
1849                         "org.freedesktop.login1.hibernate-multiple-sessions",
1850                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1851                         "hybrid-sleep",
1852                         error);
1853 }
1854
1855 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1856         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1857         const char *who, *why, *what, *mode;
1858         _cleanup_free_ char *id = NULL;
1859         _cleanup_close_ int fifo_fd = -1;
1860         Manager *m = userdata;
1861         Inhibitor *i = NULL;
1862         InhibitMode mm;
1863         InhibitWhat w;
1864         pid_t pid;
1865         uid_t uid;
1866         int r;
1867
1868         assert(bus);
1869         assert(message);
1870         assert(m);
1871
1872         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1873         if (r < 0)
1874                 return r;
1875
1876         w = inhibit_what_from_string(what);
1877         if (w <= 0)
1878                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1879
1880         mm = inhibit_mode_from_string(mode);
1881         if (mm < 0)
1882                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1883
1884         /* Delay is only supported for shutdown/sleep */
1885         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1886                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1887
1888         /* Don't allow taking delay locks while we are already
1889          * executing the operation. We shouldn't create the impression
1890          * that the lock was successful if the machine is about to go
1891          * down/suspend any moment. */
1892         if (m->action_what & w)
1893                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1894
1895         r = bus_verify_polkit_async(
1896                         message,
1897                         CAP_SYS_BOOT,
1898                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1899                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
1900                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
1901                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
1902                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1903                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1904                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
1905                         false,
1906                         UID_INVALID,
1907                         &m->polkit_registry,
1908                         error);
1909         if (r < 0)
1910                 return r;
1911         if (r == 0)
1912                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1913
1914         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1915         if (r < 0)
1916                 return r;
1917
1918         r = sd_bus_creds_get_euid(creds, &uid);
1919         if (r < 0)
1920                 return r;
1921
1922         r = sd_bus_creds_get_pid(creds, &pid);
1923         if (r < 0)
1924                 return r;
1925
1926         do {
1927                 free(id);
1928                 id = NULL;
1929
1930                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1931                         return -ENOMEM;
1932
1933         } while (hashmap_get(m->inhibitors, id));
1934
1935         r = manager_add_inhibitor(m, id, &i);
1936         if (r < 0)
1937                 return r;
1938
1939         i->what = w;
1940         i->mode = mm;
1941         i->pid = pid;
1942         i->uid = uid;
1943         i->why = strdup(why);
1944         i->who = strdup(who);
1945
1946         if (!i->why || !i->who) {
1947                 r = -ENOMEM;
1948                 goto fail;
1949         }
1950
1951         fifo_fd = inhibitor_create_fifo(i);
1952         if (fifo_fd < 0) {
1953                 r = fifo_fd;
1954                 goto fail;
1955         }
1956
1957         inhibitor_start(i);
1958
1959         return sd_bus_reply_method_return(message, "h", fifo_fd);
1960
1961 fail:
1962         if (i)
1963                 inhibitor_free(i);
1964
1965         return r;
1966 }
1967
1968 const sd_bus_vtable manager_vtable[] = {
1969         SD_BUS_VTABLE_START(0),
1970
1971         SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1972         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1973         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1974         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1975         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1976         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1977         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1978         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1979         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1980         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1981         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1982         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1983         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1984         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1985         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1986         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1987         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1988         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1989         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1990
1991         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1992         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1993         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1994         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1995         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1996         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1997         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1998         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
1999         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2000         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2001         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2002         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2003         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2004         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2005         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2006         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2007         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2008         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2009         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2010         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2011         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2012         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2013         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2014         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2015         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2016         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2017         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2018         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2019         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2020         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2021         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2022         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2023         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2024         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2025         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2026         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2027
2028         SD_BUS_SIGNAL("SessionNew", "so", 0),
2029         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2030         SD_BUS_SIGNAL("UserNew", "uo", 0),
2031         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2032         SD_BUS_SIGNAL("SeatNew", "so", 0),
2033         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2034         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2035         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2036
2037         SD_BUS_VTABLE_END
2038 };
2039
2040 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2041         int r = 0;
2042
2043         assert(s);
2044         assert(unit);
2045
2046         if (!s->started)
2047                 return r;
2048
2049         if (streq(result, "done"))
2050                 r = session_send_create_reply(s, NULL);
2051         else {
2052                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2053
2054                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2055                 r = session_send_create_reply(s, &e);
2056         }
2057
2058         return r;
2059 }
2060
2061 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2062         const char *path, *result, *unit;
2063         Manager *m = userdata;
2064         Session *session;
2065         uint32_t id;
2066         User *user;
2067         int r;
2068
2069         assert(bus);
2070         assert(message);
2071         assert(m);
2072
2073         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2074         if (r < 0) {
2075                 bus_log_parse_error(r);
2076                 return r;
2077         }
2078
2079         if (m->action_job && streq(m->action_job, path)) {
2080                 log_info("Operation finished.");
2081
2082                 /* Tell people that they now may take a lock again */
2083                 send_prepare_for(m, m->action_what, false);
2084
2085                 free(m->action_job);
2086                 m->action_job = NULL;
2087                 m->action_unit = NULL;
2088                 m->action_what = 0;
2089                 return 0;
2090         }
2091
2092         session = hashmap_get(m->session_units, unit);
2093         if (session) {
2094
2095                 if (streq_ptr(path, session->scope_job)) {
2096                         free(session->scope_job);
2097                         session->scope_job = NULL;
2098                 }
2099
2100                 session_jobs_reply(session, unit, result);
2101
2102                 session_save(session);
2103                 session_add_to_gc_queue(session);
2104         }
2105
2106         user = hashmap_get(m->user_units, unit);
2107         if (user) {
2108
2109                 if (streq_ptr(path, user->service_job)) {
2110                         free(user->service_job);
2111                         user->service_job = NULL;
2112                 }
2113
2114                 if (streq_ptr(path, user->slice_job)) {
2115                         free(user->slice_job);
2116                         user->slice_job = NULL;
2117                 }
2118
2119                 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2120                         session_jobs_reply(session, unit, result);
2121                 }
2122
2123                 user_save(user);
2124                 user_add_to_gc_queue(user);
2125         }
2126
2127         return 0;
2128 }
2129
2130 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2131         const char *path, *unit;
2132         Manager *m = userdata;
2133         Session *session;
2134         User *user;
2135         int r;
2136
2137         assert(bus);
2138         assert(message);
2139         assert(m);
2140
2141         r = sd_bus_message_read(message, "so", &unit, &path);
2142         if (r < 0) {
2143                 bus_log_parse_error(r);
2144                 return r;
2145         }
2146
2147         session = hashmap_get(m->session_units, unit);
2148         if (session)
2149                 session_add_to_gc_queue(session);
2150
2151         user = hashmap_get(m->user_units, unit);
2152         if (user)
2153                 user_add_to_gc_queue(user);
2154
2155         return 0;
2156 }
2157
2158 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2159         _cleanup_free_ char *unit = NULL;
2160         Manager *m = userdata;
2161         const char *path;
2162         Session *session;
2163         User *user;
2164         int r;
2165
2166         assert(bus);
2167         assert(message);
2168         assert(m);
2169
2170         path = sd_bus_message_get_path(message);
2171         if (!path)
2172                 return 0;
2173
2174         r = unit_name_from_dbus_path(path, &unit);
2175         if (r == -EINVAL) /* not a unit */
2176                 return 0;
2177         if (r < 0)
2178                 return r;
2179
2180         session = hashmap_get(m->session_units, unit);
2181         if (session)
2182                 session_add_to_gc_queue(session);
2183
2184         user = hashmap_get(m->user_units, unit);
2185         if (user)
2186                 user_add_to_gc_queue(user);
2187
2188         return 0;
2189 }
2190
2191 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2192         Manager *m = userdata;
2193         Session *session;
2194         Iterator i;
2195         int b, r;
2196
2197         assert(bus);
2198
2199         r = sd_bus_message_read(message, "b", &b);
2200         if (r < 0) {
2201                 bus_log_parse_error(r);
2202                 return r;
2203         }
2204
2205         if (b)
2206                 return 0;
2207
2208         /* systemd finished reloading, let's recheck all our sessions */
2209         log_debug("System manager has been reloaded, rechecking sessions...");
2210
2211         HASHMAP_FOREACH(session, m->sessions, i)
2212                 session_add_to_gc_queue(session);
2213
2214         return 0;
2215 }
2216
2217 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2218         const char *name, *old, *new;
2219         Manager *m = userdata;
2220         Session *session;
2221         Iterator i;
2222         int r;
2223
2224
2225         char *key;
2226
2227         r = sd_bus_message_read(message, "sss", &name, &old, &new);
2228         if (r < 0) {
2229                 bus_log_parse_error(r);
2230                 return r;
2231         }
2232
2233         if (isempty(old) || !isempty(new))
2234                 return 0;
2235
2236         key = set_remove(m->busnames, (char*) old);
2237         if (!key)
2238                 return 0;
2239
2240         /* Drop all controllers owned by this name */
2241
2242         free(key);
2243
2244         HASHMAP_FOREACH(session, m->sessions, i)
2245                 if (session_is_controller(session, old))
2246                         session_drop_controller(session);
2247
2248         return 0;
2249 }
2250
2251 int manager_send_changed(Manager *manager, const char *property, ...) {
2252         char **l;
2253
2254         assert(manager);
2255
2256         l = strv_from_stdarg_alloca(property);
2257
2258         return sd_bus_emit_properties_changed_strv(
2259                         manager->bus,
2260                         "/org/freedesktop/login1",
2261                         "org.freedesktop.login1.Manager",
2262                         l);
2263 }
2264
2265 int manager_dispatch_delayed(Manager *manager) {
2266         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2267         Inhibitor *offending = NULL;
2268         int r;
2269
2270         assert(manager);
2271
2272         if (manager->action_what == 0 || manager->action_job)
2273                 return 0;
2274
2275         /* Continue delay? */
2276         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2277                 _cleanup_free_ char *comm = NULL, *u = NULL;
2278
2279                 get_process_comm(offending->pid, &comm);
2280                 u = uid_to_name(offending->uid);
2281
2282                 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2283                         return 0;
2284
2285                 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2286                          offending->uid, strna(u),
2287                          offending->pid, strna(comm));
2288         }
2289
2290         /* Actually do the operation */
2291         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2292         if (r < 0) {
2293                 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2294
2295                 manager->action_unit = NULL;
2296                 manager->action_what = 0;
2297                 return r;
2298         }
2299
2300         return 1;
2301 }
2302
2303 int manager_start_scope(
2304                 Manager *manager,
2305                 const char *scope,
2306                 pid_t pid,
2307                 const char *slice,
2308                 const char *description,
2309                 const char *after, const char *after2,
2310                 sd_bus_error *error,
2311                 char **job) {
2312
2313         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2314         int r;
2315
2316         assert(manager);
2317         assert(scope);
2318         assert(pid > 1);
2319
2320         r = sd_bus_message_new_method_call(
2321                         manager->bus,
2322                         &m,
2323                         "org.freedesktop.systemd1",
2324                         "/org/freedesktop/systemd1",
2325                         "org.freedesktop.systemd1.Manager",
2326                         "StartTransientUnit");
2327         if (r < 0)
2328                 return r;
2329
2330         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2331         if (r < 0)
2332                 return r;
2333
2334         r = sd_bus_message_open_container(m, 'a', "(sv)");
2335         if (r < 0)
2336                 return r;
2337
2338         if (!isempty(slice)) {
2339                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2340                 if (r < 0)
2341                         return r;
2342         }
2343
2344         if (!isempty(description)) {
2345                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2346                 if (r < 0)
2347                         return r;
2348         }
2349
2350         if (!isempty(after)) {
2351                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2352                 if (r < 0)
2353                         return r;
2354         }
2355
2356         if (!isempty(after2)) {
2357                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2358                 if (r < 0)
2359                         return r;
2360         }
2361
2362         /* cgroup empty notification is not available in containers
2363          * currently. To make this less problematic, let's shorten the
2364          * stop timeout for sessions, so that we don't wait
2365          * forever. */
2366
2367         /* Make sure that the session shells are terminated with
2368          * SIGHUP since bash and friends tend to ignore SIGTERM */
2369         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2370         if (r < 0)
2371                 return r;
2372
2373         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2374         if (r < 0)
2375                 return r;
2376
2377         r = sd_bus_message_close_container(m);
2378         if (r < 0)
2379                 return r;
2380
2381         r = sd_bus_message_append(m, "a(sa(sv))", 0);
2382         if (r < 0)
2383                 return r;
2384
2385         r = sd_bus_call(manager->bus, m, 0, error, &reply);
2386         if (r < 0)
2387                 return r;
2388
2389         if (job) {
2390                 const char *j;
2391                 char *copy;
2392
2393                 r = sd_bus_message_read(reply, "o", &j);
2394                 if (r < 0)
2395                         return r;
2396
2397                 copy = strdup(j);
2398                 if (!copy)
2399                         return -ENOMEM;
2400
2401                 *job = copy;
2402         }
2403
2404         return 1;
2405 }
2406
2407 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2408         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2409         int r;
2410
2411         assert(manager);
2412         assert(unit);
2413
2414         r = sd_bus_call_method(
2415                         manager->bus,
2416                         "org.freedesktop.systemd1",
2417                         "/org/freedesktop/systemd1",
2418                         "org.freedesktop.systemd1.Manager",
2419                         "StartUnit",
2420                         error,
2421                         &reply,
2422                         "ss", unit, "fail");
2423         if (r < 0)
2424                 return r;
2425
2426         if (job) {
2427                 const char *j;
2428                 char *copy;
2429
2430                 r = sd_bus_message_read(reply, "o", &j);
2431                 if (r < 0)
2432                         return r;
2433
2434                 copy = strdup(j);
2435                 if (!copy)
2436                         return -ENOMEM;
2437
2438                 *job = copy;
2439         }
2440
2441         return 1;
2442 }
2443
2444 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2445         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2446         int r;
2447
2448         assert(manager);
2449         assert(unit);
2450
2451         r = sd_bus_call_method(
2452                         manager->bus,
2453                         "org.freedesktop.systemd1",
2454                         "/org/freedesktop/systemd1",
2455                         "org.freedesktop.systemd1.Manager",
2456                         "StopUnit",
2457                         error,
2458                         &reply,
2459                         "ss", unit, "fail");
2460         if (r < 0) {
2461                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2462                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2463
2464                         if (job)
2465                                 *job = NULL;
2466
2467                         sd_bus_error_free(error);
2468                         return 0;
2469                 }
2470
2471                 return r;
2472         }
2473
2474         if (job) {
2475                 const char *j;
2476                 char *copy;
2477
2478                 r = sd_bus_message_read(reply, "o", &j);
2479                 if (r < 0)
2480                         return r;
2481
2482                 copy = strdup(j);
2483                 if (!copy)
2484                         return -ENOMEM;
2485
2486                 *job = copy;
2487         }
2488
2489         return 1;
2490 }
2491
2492 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2493         _cleanup_free_ char *path = NULL;
2494         int r;
2495
2496         assert(manager);
2497         assert(scope);
2498
2499         path = unit_dbus_path_from_name(scope);
2500         if (!path)
2501                 return -ENOMEM;
2502
2503         r = sd_bus_call_method(
2504                         manager->bus,
2505                         "org.freedesktop.systemd1",
2506                         path,
2507                         "org.freedesktop.systemd1.Scope",
2508                         "Abandon",
2509                         error,
2510                         NULL,
2511                         NULL);
2512         if (r < 0) {
2513                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2514                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2515                     sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2516                         sd_bus_error_free(error);
2517                         return 0;
2518                 }
2519
2520                 return r;
2521         }
2522
2523         return 1;
2524 }
2525
2526 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2527         assert(manager);
2528         assert(unit);
2529
2530         return sd_bus_call_method(
2531                         manager->bus,
2532                         "org.freedesktop.systemd1",
2533                         "/org/freedesktop/systemd1",
2534                         "org.freedesktop.systemd1.Manager",
2535                         "KillUnit",
2536                         error,
2537                         NULL,
2538                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2539 }
2540
2541 int manager_unit_is_active(Manager *manager, const char *unit) {
2542         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2543         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2544         _cleanup_free_ char *path = NULL;
2545         const char *state;
2546         int r;
2547
2548         assert(manager);
2549         assert(unit);
2550
2551         path = unit_dbus_path_from_name(unit);
2552         if (!path)
2553                 return -ENOMEM;
2554
2555         r = sd_bus_get_property(
2556                         manager->bus,
2557                         "org.freedesktop.systemd1",
2558                         path,
2559                         "org.freedesktop.systemd1.Unit",
2560                         "ActiveState",
2561                         &error,
2562                         &reply,
2563                         "s");
2564         if (r < 0) {
2565                 /* systemd might have droppped off momentarily, let's
2566                  * not make this an error */
2567                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2568                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2569                         return true;
2570
2571                 /* If the unit is already unloaded then it's not
2572                  * active */
2573                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2574                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2575                         return false;
2576
2577                 return r;
2578         }
2579
2580         r = sd_bus_message_read(reply, "s", &state);
2581         if (r < 0)
2582                 return -EINVAL;
2583
2584         return !streq(state, "inactive") && !streq(state, "failed");
2585 }
2586
2587 int manager_job_is_active(Manager *manager, const char *path) {
2588         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2589         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2590         int r;
2591
2592         assert(manager);
2593         assert(path);
2594
2595         r = sd_bus_get_property(
2596                         manager->bus,
2597                         "org.freedesktop.systemd1",
2598                         path,
2599                         "org.freedesktop.systemd1.Job",
2600                         "State",
2601                         &error,
2602                         &reply,
2603                         "s");
2604         if (r < 0) {
2605                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2606                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2607                         return true;
2608
2609                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2610                         return false;
2611
2612                 return r;
2613         }
2614
2615         /* We don't actually care about the state really. The fact
2616          * that we could read the job state is enough for us */
2617
2618         return true;
2619 }