diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index f312ef2b99a..66d40fca451 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -222,6 +222,66 @@
operating system
provides.
+
+
+
+ The following environment variables are read by
+ the module and may be used by the PAM service to pass
+ meta data to the module:
+
+
+
+ $XDG_SESSION_TYPE
+
+ The session type. This
+ may be used instead of
+ on the
+ module parameter line, and is usually
+ preferred.
+
+
+
+ $XDG_SESSION_CLASS
+
+ The session class. This
+ may be used instead of
+ on the
+ module parameter line, and is usually
+ preferred.
+
+
+
+ $XDG_SESSION_DESKTOP
+
+ The session
+ deskop. This may be used to indicate
+ the session desktop used, where this
+ applies. This should be a short,
+ lowercase string identifying the
+ desktop environment used if this
+ information is available. For example:
+ gnome, or
+ kde.
+
+
+
+ $XDG_SEAT
+
+ The seat name the session
+ shall be registered for, if
+ any.
+
+
+
+ $XDG_VTNR
+
+ The VT number the
+ session shall be registered for, if
+ any. (Only applies to seats with a VT
+ available, such as
+ seat0)
+
+
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 6900253b0d4..ebe9c1f16ce 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -271,6 +271,7 @@ typedef struct SessionStatusInfo {
const char *class;
const char *state;
const char *scope;
+ const char *desktop;
} SessionStatusInfo;
typedef struct UserStatusInfo {
@@ -363,6 +364,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
{ "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
{ "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
{ "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
+ { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
{ "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
{ "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
{ "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
@@ -462,6 +464,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
} else if (i.class)
printf("\t Class: %s\n", i.class);
+ if (!isempty(i.desktop))
+ printf("\t Desktop: %s\n", i.desktop);
+
if (i.state)
printf("\t State: %s\n", i.state);
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 2c86b9fa264..47459617733 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -450,7 +450,7 @@ static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *us
}
static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host;
+ const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
uint32_t uid, leader, audit_id = 0;
_cleanup_free_ char *id = NULL;
Session *session = NULL;
@@ -467,7 +467,7 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
assert(message);
assert(m);
- r = sd_bus_message_read(message, "uussssussbss", &uid, &leader, &service, &type, &class, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
+ r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
if (r < 0)
return r;
@@ -490,6 +490,13 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
}
+ if (isempty(desktop))
+ desktop = NULL;
+ else {
+ if (!string_is_safe(desktop))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
+ }
+
if (isempty(cseat))
seat = NULL;
else {
@@ -550,10 +557,10 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
}
if (c == _SESSION_CLASS_INVALID) {
- if (!isempty(display) || !isempty(tty))
- c = SESSION_USER;
- else
+ if (t == SESSION_UNSPECIFIED)
c = SESSION_BACKGROUND;
+ else
+ c = SESSION_USER;
}
if (leader <= 0) {
@@ -687,6 +694,14 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
}
}
+ if (!isempty(desktop)) {
+ session->desktop = strdup(desktop);
+ if (!session->desktop) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
if (seat) {
r = seat_attach_session(seat, session);
if (r < 0)
@@ -1864,7 +1879,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CreateSession", "uussssussbssa(sv)", "soshusub", method_create_session, 0),
+ SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 54ad827feb2..7ee49562cf1 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -444,6 +444,7 @@ const sd_bus_vtable session_vtable[] = {
SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 4f3259ca7cd..ca2e48570c7 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -143,6 +143,7 @@ void session_free(Session *s) {
free(s->remote_host);
free(s->remote_user);
free(s->service);
+ free(s->desktop);
hashmap_remove(s->manager->sessions, s->id);
@@ -229,6 +230,9 @@ int session_save(Session *s) {
if (s->service)
fprintf(f, "SERVICE=%s\n", s->service);
+ if (s->desktop)
+ fprintf(f, "DESKTOP=%s\n", s->desktop);
+
if (s->seat && seat_has_vts(s->seat))
fprintf(f, "VTNR=%u\n", s->vtnr);
@@ -294,6 +298,7 @@ int session_load(Session *s) {
"REMOTE_HOST", &s->remote_host,
"REMOTE_USER", &s->remote_user,
"SERVICE", &s->service,
+ "DESKTOP", &s->desktop,
"VTNR", &vtnr,
"POS", &pos,
"LEADER", &leader,
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 202d28752f0..7bf19320323 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -87,6 +87,7 @@ struct Session {
char *remote_user;
char *remote_host;
char *service;
+ char *desktop;
char *scope;
char *scope_job;
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
index 9f0f7d18665..3b2966b30cf 100644
--- a/src/login/pam-module.c
+++ b/src/login/pam-module.c
@@ -212,7 +212,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
*remote_user = NULL, *remote_host = NULL,
*seat = NULL,
*type = NULL, *class = NULL,
- *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL;
+ *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
_cleanup_bus_unref_ sd_bus *bus = NULL;
int session_fd = -1, existing, r;
bool debug = false, remote;
@@ -303,8 +303,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (isempty(class))
class = class_pam;
+ desktop = pam_getenv(handle, "XDG_SESSION_DESKTOP");
+ if (isempty(desktop))
+ desktop = getenv("XDG_SESSION_DESKTOP");
+
tty = strempty(tty);
- display = strempty(display);
if (strchr(tty, ':')) {
/* A tty with a colon is usually an X11 display,
@@ -314,21 +317,21 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (isempty(display))
display = tty;
- tty = "";
+ tty = NULL;
} else if (streq(tty, "cron")) {
/* cron has been setting PAM_TTY to "cron" for a very
* long time and it probably shouldn't stop doing that
* for compatibility reasons. */
type = "unspecified";
class = "background";
- tty = "";
+ tty = NULL;
} else if (streq(tty, "ssh")) {
/* ssh has been setting PAM_TTY to "ssh" for a very
* long time and probably shouldn't stop doing that
* for compatibility reasons. */
type ="tty";
class = "user";
- tty = "";
+ tty = NULL;
}
/* If this fails vtnr will be 0, that's intended */
@@ -368,11 +371,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (debug)
pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
- "uid=%u pid=%u service=%s type=%s class=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
+ "uid=%u pid=%u service=%s type=%s class=%s desktop=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
pw->pw_uid, getpid(),
strempty(service),
- type, class,
- strempty(seat), vtnr, tty, strempty(display),
+ type, class, desktop,
+ strempty(seat), vtnr, strempty(tty), strempty(display),
yes_no(remote), strempty(remote_user), strempty(remote_host));
r = sd_bus_call_method(bus,
@@ -382,19 +385,20 @@ _public_ PAM_EXTERN int pam_sm_open_session(
"CreateSession",
&error,
&reply,
- "uussssussbssa(sv)",
+ "uusssssussbssa(sv)",
(uint32_t) pw->pw_uid,
(uint32_t) getpid(),
- strempty(service),
+ service,
type,
class,
- strempty(seat),
+ desktop,
+ seat,
vtnr,
tty,
- strempty(display),
+ display,
remote,
- strempty(remote_user),
- strempty(remote_host),
+ remote_user,
+ remote_host,
0);
if (r < 0) {
pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));