pam: add session class "none" to disable logind sessions (#35171)
pam_systemd is used to create logind sessions and to apply extended attributes from json user records. Not every application that creates a pam session expects a login scope, but may be interested in the extended attributes of json user records. Session class "none" implements this service by disabling logind for this session altogether. --- Closes: #34988
This commit is contained in:
@@ -143,6 +143,10 @@
|
||||
<entry><constant>manager-early</constant></entry>
|
||||
<entry>Similar to <constant>manager</constant>, but for the root user. Compare with the <constant>user</constant> vs. <constant>user-early</constant> situation. (Added in v256.)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>none</constant></entry>
|
||||
<entry>Skips registering this session with logind. No session scope will be created, and the user service manager will not be started. (Added in v258.)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
+21
-18
@@ -911,6 +911,27 @@ static int create_session(
|
||||
if (!uid_is_valid(uid))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
|
||||
|
||||
if (isempty(type))
|
||||
t = _SESSION_TYPE_INVALID;
|
||||
else {
|
||||
t = session_type_from_string(type);
|
||||
if (t < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid session type %s", type);
|
||||
}
|
||||
|
||||
if (isempty(class))
|
||||
c = _SESSION_CLASS_INVALID;
|
||||
else {
|
||||
c = session_class_from_string(class);
|
||||
if (c < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid session class %s", class);
|
||||
if (c == SESSION_NONE)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Refusing session class %s", class);
|
||||
}
|
||||
|
||||
if (flags != 0)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero.");
|
||||
|
||||
@@ -930,24 +951,6 @@ static int create_session(
|
||||
if (leader.pid == 1 || pidref_is_self(&leader))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
|
||||
|
||||
if (isempty(type))
|
||||
t = _SESSION_TYPE_INVALID;
|
||||
else {
|
||||
t = session_type_from_string(type);
|
||||
if (t < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid session type %s", type);
|
||||
}
|
||||
|
||||
if (isempty(class))
|
||||
c = _SESSION_CLASS_INVALID;
|
||||
else {
|
||||
c = session_class_from_string(class);
|
||||
if (c < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid session class %s", class);
|
||||
}
|
||||
|
||||
if (isempty(desktop))
|
||||
desktop = NULL;
|
||||
else {
|
||||
|
||||
@@ -1678,6 +1678,7 @@ static const char* const session_class_table[_SESSION_CLASS_MAX] = {
|
||||
[SESSION_BACKGROUND_LIGHT] = "background-light",
|
||||
[SESSION_MANAGER] = "manager",
|
||||
[SESSION_MANAGER_EARLY] = "manager-early",
|
||||
[SESSION_NONE] = "none",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
|
||||
|
||||
@@ -29,6 +29,7 @@ typedef enum SessionClass {
|
||||
SESSION_BACKGROUND_LIGHT, /* Like SESSION_BACKGROUND, but without the service manager */
|
||||
SESSION_MANAGER, /* The service manager */
|
||||
SESSION_MANAGER_EARLY, /* The service manager for root (which is allowed to run before systemd-user-sessions.service) */
|
||||
SESSION_NONE, /* A session not registered with logind */
|
||||
_SESSION_CLASS_MAX,
|
||||
_SESSION_CLASS_INVALID = -EINVAL,
|
||||
} SessionClass;
|
||||
@@ -44,7 +45,7 @@ typedef enum SessionClass {
|
||||
#define SESSION_CLASS_WANTS_SERVICE_MANAGER(class) IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER, SESSION_LOCK_SCREEN, SESSION_BACKGROUND)
|
||||
|
||||
/* Which session classes can pin our user tracking? */
|
||||
#define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY))
|
||||
#define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY, SESSION_NONE))
|
||||
|
||||
/* Which session classes decide whether system is idle? (should only cover sessions that have input, and are not idle screens themselves)*/
|
||||
#define SESSION_CLASS_CAN_IDLE(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER))
|
||||
|
||||
@@ -1043,6 +1043,12 @@ static int register_session(
|
||||
assert(ur);
|
||||
assert(ret_seat);
|
||||
|
||||
/* We don't register session class none with logind */
|
||||
if (streq(c->class, "none")) {
|
||||
pam_debug_syslog(handle, debug, "Skipping logind registration for session class none");
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* Make most of this a NOP on non-logind systems */
|
||||
if (!logind_running())
|
||||
goto skip;
|
||||
|
||||
@@ -701,13 +701,14 @@ background_at_return() {
|
||||
|
||||
testcase_background() {
|
||||
|
||||
local uid TRANSIENTUNIT1 TRANSIENTUNIT2
|
||||
local uid TRANSIENTUNIT0 TRANSIENTUNIT1 TRANSIENTUNIT2
|
||||
|
||||
uid=$(id -u logind-test-user)
|
||||
|
||||
systemctl stop user@"$uid".service
|
||||
|
||||
PAMSERVICE="pamserv$RANDOM"
|
||||
TRANSIENTUNIT0="none$RANDOM.service"
|
||||
TRANSIENTUNIT1="bg$RANDOM.service"
|
||||
TRANSIENTUNIT2="bgg$RANDOM.service"
|
||||
|
||||
@@ -722,6 +723,13 @@ session optional pam_systemd.so debug
|
||||
session required pam_unix.so
|
||||
EOF
|
||||
|
||||
systemd-run -u "$TRANSIENTUNIT0" -p PAMName="$PAMSERVICE" -p "Environment=XDG_SESSION_CLASS=none" -p Type=exec -p User=logind-test-user sleep infinity
|
||||
|
||||
# This was a 'none' service, so logind should take no action
|
||||
(! systemctl is-active user@"$uid".service )
|
||||
|
||||
systemctl stop "$TRANSIENTUNIT0"
|
||||
|
||||
systemd-run -u "$TRANSIENTUNIT1" -p PAMName="$PAMSERVICE" -p "Environment=XDG_SESSION_CLASS=background-light" -p Type=exec -p User=logind-test-user sleep infinity
|
||||
|
||||
# This was a 'light' background service, hence the service manager should not be running
|
||||
|
||||
Reference in New Issue
Block a user