diff options
Diffstat (limited to 'src/login/pam_systemd.c')
-rw-r--r-- | src/login/pam_systemd.c | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index c7d9dcf4e2..997b74eb88 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -28,6 +28,7 @@ #include "path-util.h" #include "process-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" @@ -190,6 +191,45 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_ return 0; } +static int export_legacy_dbus_address( + pam_handle_t *handle, + uid_t uid, + const char *runtime) { + + const char *s; + _cleanup_free_ char *t = NULL; + int r = PAM_BUF_ERR; + + /* We need to export $DBUS_SESSION_BUS_ADDRESS because various applications will not connect + * correctly to the bus without it. This setting matches what dbus.socket does for the user + * session using 'systemctl --user set-environment'. We want to have the same configuration + * in processes started from the PAM session. + * + * The setting of the address is guarded by the access() check because it is also possible to compile + * dbus without --enable-user-session, in which case this socket is not used, and + * $DBUS_SESSION_BUS_ADDRESS should not be set. An alternative approach would to not do the access() + * check here, and let applications try on their own, by using "unix:path=%s/bus;autolaunch:". But we + * expect the socket to be present by the time we do this check, so we can just as well check once + * here. */ + + s = strjoina(runtime, "/bus"); + if (access(s, F_OK) < 0) + return PAM_SUCCESS; + + if (asprintf(&t, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0) + goto error; + + r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", t, 0); + if (r != PAM_SUCCESS) + goto error; + + return PAM_SUCCESS; + +error: + pam_syslog(handle, LOG_ERR, "Failed to set bus variable."); + return r; +} + static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { uint64_t val; int r; @@ -392,11 +432,9 @@ _public_ PAM_EXTERN int pam_sm_open_session( pam_get_item(handle, PAM_SERVICE, (const void**) &service); if (streq_ptr(service, "systemd-user")) { - _cleanup_free_ char *rt = NULL; - - if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0) - return PAM_BUF_ERR; + char rt[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)]; + xsprintf(rt, "/run/user/"UID_FMT, pw->pw_uid); if (validate_runtime_directory(handle, rt, pw->pw_uid)) { r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); if (r != PAM_SUCCESS) { @@ -405,6 +443,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( } } + r = export_legacy_dbus_address(handle, pw->pw_uid, rt); + if (r != PAM_SUCCESS) + return r; + return PAM_SUCCESS; } @@ -569,7 +611,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) { if (debug) - pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r)); + pam_syslog(handle, LOG_DEBUG, "Not creating session: %s", bus_error_message(&error, r)); return PAM_SUCCESS; } else { pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r)); @@ -613,6 +655,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (r != PAM_SUCCESS) return r; } + + r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); + if (r != PAM_SUCCESS) + return r; } /* Most likely we got the session/type/class from environment variables, but might have gotten the data |