#include "utmp-wtmp.h"
#include "virt.h"
-static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
+static int get_sender_session(
+ Manager *m,
+ sd_bus_message *message,
+ bool consult_display,
+ sd_bus_error *error,
+ Session **ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ Session *session = NULL;
const char *name;
- Session *session;
int r;
- /* Get client login session. This is not what you are looking for these days,
- * as apps may instead belong to a user service unit. This includes terminal
- * emulators and hence command-line apps. */
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+ /* Acquire the sender's session. This first checks if the sending process is inside a session itself,
+ * and returns that. If not and 'consult_display' is true, this returns the display session of the
+ * owning user of the caller. */
+
+ r = sd_bus_query_sender_creds(message,
+ SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT|
+ (consult_display ? SD_BUS_CREDS_OWNER_UID : 0), &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_session(creds, &name);
- if (r == -ENXIO)
- goto err_no_session;
- if (r < 0)
- return r;
+ if (r < 0) {
+ if (r != -ENXIO)
+ return r;
+
+ if (consult_display) {
+ uid_t uid;
+
+ r = sd_bus_creds_get_owner_uid(creds, &uid);
+ if (r < 0) {
+ if (r != -ENXIO)
+ return r;
+ } else {
+ User *user;
+
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
+ if (user)
+ session = user->display;
+ }
+ }
+ } else
+ session = hashmap_get(m->sessions, name);
- session = hashmap_get(m->sessions, name);
if (!session)
- goto err_no_session;
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
+ consult_display ?
+ "Caller does not belong to any known session and doesn't own any suitable session." :
+ "Caller does not belong to any known session.");
*ret = session;
return 0;
-
-err_no_session:
- return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
- "Caller does not belong to any known session");
}
-int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
+int manager_get_session_from_creds(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name,
+ sd_bus_error *error,
+ Session **ret) {
+
Session *session;
assert(m);
assert(message);
assert(ret);
- if (isempty(name))
- return get_sender_session(m, message, error, ret);
+ if (SEAT_IS_SELF(name)) /* the caller's own session */
+ return get_sender_session(m, message, false, error, ret);
+ if (SEAT_IS_AUTO(name)) /* The caller's own session if they have one, otherwise their user's display session */
+ return get_sender_session(m, message, true, error, ret);
session = hashmap_get(m->sessions, name);
if (!session)
}
static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
-
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t uid;
User *user;
return r;
r = sd_bus_creds_get_owner_uid(creds, &uid);
- if (r == -ENXIO)
- goto err_no_user;
- if (r < 0)
- return r;
+ if (r < 0) {
+ if (r != -ENXIO)
+ return r;
+
+ user = NULL;
+ } else
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
- user = hashmap_get(m->users, UID_TO_PTR(uid));
if (!user)
- goto err_no_user;
+ return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
+ "Caller does not belong to any logged in or lingering user");
*ret = user;
return 0;
-
-err_no_user:
- return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
- "Caller does not belong to any logged in user or lingering user");
}
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
return 0;
}
-int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
+int manager_get_seat_from_creds(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name,
+ sd_bus_error *error,
+ Seat **ret) {
+
Seat *seat;
int r;
assert(message);
assert(ret);
- if (isempty(name)) {
+ if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) {
Session *session;
- r = manager_get_session_from_creds(m, message, NULL, error, &session);
+ /* Use these special seat names as session names */
+ r = manager_get_session_from_creds(m, message, name, error, &session);
if (r < 0)
return r;
seat = session->seat;
if (!seat)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session '%s' has no seat.", session->id);
} else {
seat = hashmap_get(m->seats, name);
if (!seat)
} while (hashmap_get(m->sessions, id));
}
+ /* The generated names should not clash with 'auto' or 'self' */
+ assert(!SESSION_IS_SELF(id));
+ assert(!SESSION_IS_AUTO(id));
+
/* If we are not watching utmp already, try again */
manager_reconnect_utmp(m);
assert(message);
assert(m);
- /* Same as ActivateSession() but refuses to work if
- * the seat doesn't match */
+ /* Same as ActivateSession() but refuses to work if the seat doesn't match */
r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
if (r < 0)
};
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+ _cleanup_free_ char *e = NULL;
+ sd_bus_message *message;
Manager *m = userdata;
+ const char *p;
Seat *seat;
int r;
assert(found);
assert(m);
- if (streq(path, "/org/freedesktop/login1/seat/self")) {
- sd_bus_message *message;
-
- message = sd_bus_get_current_message(bus);
- if (!message)
- return 0;
-
- r = manager_get_seat_from_creds(m, message, NULL, error, &seat);
- if (r < 0)
- return r;
- } else {
- _cleanup_free_ char *e = NULL;
- const char *p;
+ p = startswith(path, "/org/freedesktop/login1/seat/");
+ if (!p)
+ return 0;
- p = startswith(path, "/org/freedesktop/login1/seat/");
- if (!p)
- return 0;
+ e = bus_label_unescape(p);
+ if (!e)
+ return -ENOMEM;
- e = bus_label_unescape(p);
- if (!e)
- return -ENOMEM;
+ message = sd_bus_get_current_message(bus);
+ if (!message)
+ return 0;
- seat = hashmap_get(m->seats, e);
- if (!seat)
- return 0;
+ r = manager_get_seat_from_creds(m, message, e, error, &seat);
+ if (r == -ENXIO) {
+ sd_bus_error_free(error);
+ return 0;
}
+ if (r < 0)
+ return r;
*found = seat;
return 1;
message = sd_bus_get_current_message(bus);
if (message) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- const char *name;
- Session *session;
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) {
+ bool may_auto = false;
+ const char *name;
+
r = sd_bus_creds_get_session(creds, &name);
if (r >= 0) {
+ Session *session;
+
session = hashmap_get(m->sessions, name);
if (session && session->seat) {
r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
if (r < 0)
return r;
+
+ may_auto = true;
}
}
+
+ if (!may_auto) {
+ uid_t uid;
+
+ r = sd_bus_creds_get_owner_uid(creds, &uid);
+ if (r >= 0) {
+ User *user;
+
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
+ may_auto = user && user->display && user->display->seat;
+ }
+ }
+
+ if (may_auto) {
+ r = strv_extend(&l, "/org/freedesktop/login1/seat/auto");
+ if (r < 0)
+ return r;
+ }
}
}
*nodes = TAKE_PTR(l);
-
return 1;
}
#include "signal-util.h"
#include "stat-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
static int property_get_user(
};
int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+ _cleanup_free_ char *e = NULL;
+ sd_bus_message *message;
Manager *m = userdata;
Session *session;
+ const char *p;
int r;
assert(bus);
assert(found);
assert(m);
- if (streq(path, "/org/freedesktop/login1/session/self")) {
- sd_bus_message *message;
-
- message = sd_bus_get_current_message(bus);
- if (!message)
- return 0;
-
- r = manager_get_session_from_creds(m, message, NULL, error, &session);
- if (r < 0)
- return r;
- } else {
- _cleanup_free_ char *e = NULL;
- const char *p;
+ p = startswith(path, "/org/freedesktop/login1/session/");
+ if (!p)
+ return 0;
- p = startswith(path, "/org/freedesktop/login1/session/");
- if (!p)
- return 0;
+ e = bus_label_unescape(p);
+ if (!e)
+ return -ENOMEM;
- e = bus_label_unescape(p);
- if (!e)
- return -ENOMEM;
+ message = sd_bus_get_current_message(bus);
+ if (!message)
+ return 0;
- session = hashmap_get(m->sessions, e);
- if (!session)
- return 0;
+ r = manager_get_session_from_creds(m, message, e, error, &session);
+ if (r == -ENXIO) {
+ sd_bus_error_free(error);
+ return 0;
}
+ if (r < 0)
+ return r;
*found = session;
return 1;
message = sd_bus_get_current_message(bus);
if (message) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- const char *name;
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) {
+ bool may_auto = false;
+ const char *name;
+
r = sd_bus_creds_get_session(creds, &name);
if (r >= 0) {
session = hashmap_get(m->sessions, name);
r = strv_extend(&l, "/org/freedesktop/login1/session/self");
if (r < 0)
return r;
+
+ may_auto = true;
+ }
+ }
+
+ if (!may_auto) {
+ uid_t uid;
+
+ r = sd_bus_creds_get_owner_uid(creds, &uid);
+ if (r >= 0) {
+ User *user;
+
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
+ may_auto = user && user->display;
}
}
+
+ if (may_auto) {
+ r = strv_extend(&l, "/org/freedesktop/login1/session/auto");
+ if (r < 0)
+ return r;
+ }
}
}
*nodes = TAKE_PTR(l);
-
return 1;
}