diff options
Diffstat (limited to 'src/login/pam_elogind.c')
-rw-r--r-- | src/login/pam_elogind.c | 124 |
1 files changed, 60 insertions, 64 deletions
diff --git a/src/login/pam_elogind.c b/src/login/pam_elogind.c index 88c5705ef..c4550d35b 100644 --- a/src/login/pam_elogind.c +++ b/src/login/pam_elogind.c @@ -130,7 +130,7 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_ r = socket_from_display(display, &p); if (r < 0) return r; - strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1); + strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd < 0) @@ -160,40 +160,6 @@ 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) { - - _cleanup_free_ char *s = NULL; - int r = PAM_BUF_ERR; - - /* FIXME: We *really* should move the access() check into the - * daemons that spawn dbus-daemon, instead of forcing - * DBUS_SESSION_BUS_ADDRESS= here. */ - - s = strjoin(runtime, "/bus"); - if (!s) - goto error; - - if (access(s, F_OK) < 0) - return PAM_SUCCESS; - - s = mfree(s); - if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0) - goto error; - - r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 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; @@ -274,6 +240,36 @@ static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, con return 0; } +static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) { + struct stat st; + + assert(path); + + /* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set + * up properly for us. */ + + if (lstat(path, &st) < 0) { + pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno)); + goto fail; + } + + if (!S_ISDIR(st.st_mode)) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not actually a directory.", path); + goto fail; + } + + if (st.st_uid != uid) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not owned by UID " UID_FMT ", as it should.", path, uid); + goto fail; + } + + return true; + +fail: + pam_syslog(handle, LOG_WARNING, "Not setting $XDG_RUNTIME_DIR, as the directory is not in order."); + return false; +} + _public_ PAM_EXTERN int pam_sm_open_session( pam_handle_t *handle, int flags, @@ -334,16 +330,14 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0) return PAM_BUF_ERR; - r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - return r; + if (validate_runtime_directory(handle, rt, pw->pw_uid)) { + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); + return r; + } } - r = export_legacy_dbus_address(handle, pw->pw_uid, rt); - if (r != PAM_SUCCESS) - return r; - return PAM_SUCCESS; } @@ -381,28 +375,32 @@ _public_ PAM_EXTERN int pam_sm_open_session( tty = strempty(tty); if (strchr(tty, ':')) { - /* A tty with a colon is usually an X11 display, - * placed there to show up in utmp. We rearrange - * things and don't pretend that an X display was a - * tty. */ - + /* A tty with a colon is usually an X11 display, placed there to show up in utmp. We rearrange things + * and don't pretend that an X display was a tty. */ if (isempty(display)) display = 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. */ + /* cron is setting PAM_TTY to "cron" for some reason (the commit carries no information why, but + * probably because it wants to set it to something as pam_time/pam_access/… require PAM_TTY to be set + * (as they otherwise even try to update it!) — but cron doesn't actually allocate a TTY for its forked + * off processes.) */ type = "unspecified"; class = "background"; 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. */ + /* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further + * details look for "PAM_TTY_KLUDGE" in the openssh sources). */ type ="tty"; class = "user"; - tty = NULL; + tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually + * associated with a pty — won't be tracked by their tty in logind. This is because ssh + * does the PAM session registration early for new connections, and registers a pty only + * much later (this is because it doesn't know yet if it needs one at all, as whether to + * register a pty or not is negotiated much later in the protocol). */ + } else /* Chop off leading /dev prefix that some clients specify, but others do not. */ tty = skip_dev_prefix(tty); @@ -472,7 +470,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( r = sd_bus_message_append(m, "uusssssussbss", (uint32_t) pw->pw_uid, - (uint32_t) getpid_cached(), + 0, service, type, class, @@ -561,15 +559,13 @@ _public_ PAM_EXTERN int pam_sm_open_session( * in privileged apps clobbering the runtime directory * unnecessarily. */ - r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - return r; + if (validate_runtime_directory(handle, runtime_path, pw->pw_uid)) { + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); + return r; + } } - - r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); - if (r != PAM_SUCCESS) - return r; } if (!isempty(seat)) { |