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