diff options
Diffstat (limited to 'src/openrc-pam')
-rw-r--r-- | src/openrc-pam/openrc-pam.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/src/openrc-pam/openrc-pam.c b/src/openrc-pam/openrc-pam.c index 2a66ab4a..d4b39da8 100644 --- a/src/openrc-pam/openrc-pam.c +++ b/src/openrc-pam/openrc-pam.c @@ -1,13 +1,15 @@ +#define _XOPEN_SOURCE 500 +#include <ftw.h> #include <librc.h> #include <pwd.h> #include <security/pam_appl.h> #include <security/pam_modules.h> #include <stdbool.h> #include <stdio.h> -#include <syslog.h> +#include <string.h> #include <sys/file.h> +#include <syslog.h> #include <unistd.h> -#include <string.h> #include "einfo.h" #include "queue.h" @@ -163,25 +165,33 @@ exec_user_cmd(struct passwd *pw, char *cmd, char **envlist) return retval; } -static char *create_xdg_runtime_dir(struct passwd *pw) { +static char *create_rc_runtime_dir(struct passwd *pw) { char *path = NULL; - if (mkdir("/run/user", 0755) != 0 && errno != EEXIST) + if (mkdir("/run/openrc/user", 0755) != 0 && errno != EEXIST) return NULL; - xasprintf(&path, "/run/user/%d/", pw->pw_uid); + xasprintf(&path, "/run/openrc/user/%d/", pw->pw_uid); if (mkdir(path, 0700) != 0 && errno != EEXIST) { free(path); return NULL; } - if (chown(path, pw->pw_uid, pw->pw_gid) != 0) { - free(path); - return NULL; + return path; +} + +static int clear_runtime_dir(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { + int ret = remove(path) != 0; + (void)sb; + (void)typeflag; + (void)ftwbuf; + + if (ret != 0) { + elog(LOG_ERR, "Failed to remove %s: %s", path, strerror(errno)); } - return path; + return ret; } static bool exec_openrc(pam_handle_t *pamh, const char *runlevel, bool lock) { @@ -189,9 +199,8 @@ static bool exec_openrc(pam_handle_t *pamh, const char *runlevel, bool lock) { char *cmd = NULL; const char *username; struct passwd *pw = NULL; - char *xdg_runtime_dir; - char *xdg_runtime_dir_env; char *openrc_runtime_dir; + char *openrc_runtime_dir_env; char **envlist; char **env; @@ -201,29 +210,27 @@ static bool exec_openrc(pam_handle_t *pamh, const char *runlevel, bool lock) { if (!pw) return false; - /* XDG_RUNTIME_DIR is needed in so many places, that if it's not defined - * we're defining it on the standard location. */ + /* avoid setting RC_RUNTIME_DIR if XDG_RUNTIME_DIR is already set by the user's stack */ if (pam_getenv(pamh, "XDG_RUNTIME_DIR") == NULL) { - xdg_runtime_dir = create_xdg_runtime_dir(pw); - if (!xdg_runtime_dir) { + openrc_runtime_dir = create_rc_runtime_dir(pw); + if (!openrc_runtime_dir) { return false; } - xasprintf(&xdg_runtime_dir_env, "XDG_RUNTIME_DIR=%s", xdg_runtime_dir); - pam_putenv(pamh, xdg_runtime_dir_env); - elog(LOG_INFO, "exporting: %s", xdg_runtime_dir_env); - free(xdg_runtime_dir); - free(xdg_runtime_dir_env); - } - - xasprintf(&openrc_runtime_dir, "%s/%s", pam_getenv(pamh, "XDG_RUNTIME_DIR"), "openrc"); - - if (mkdir(openrc_runtime_dir, 0700) != 0 && errno != EEXIST) { - free(openrc_runtime_dir); - return false; + xasprintf(&openrc_runtime_dir_env, "RC_RUNTIME_DIR=%s", openrc_runtime_dir); + pam_putenv(pamh, openrc_runtime_dir_env); + elog(LOG_INFO, "exporting: %s", openrc_runtime_dir_env); + free(openrc_runtime_dir_env); + } else { + xasprintf(&openrc_runtime_dir, "%s/%s", pam_getenv(pamh, "XDG_RUNTIME_DIR"), "openrc"); + if (mkdir(openrc_runtime_dir, 0700) != 0 && errno != EEXIST) { + free(openrc_runtime_dir); + return false; + } } if (chown(openrc_runtime_dir, pw->pw_uid, pw->pw_gid) != 0) { + rmdir(openrc_runtime_dir); free(openrc_runtime_dir); return false; } @@ -239,6 +246,10 @@ static bool exec_openrc(pam_handle_t *pamh, const char *runlevel, bool lock) { if (lockval == 0) { elog(LOG_INFO, "Executing %s for user %s", cmd, username); exec_user_cmd(pw, cmd, envlist); + + if (!lock) { + nftw(openrc_runtime_dir, clear_runtime_dir, 64, FTW_DEPTH | FTW_PHYS); + } } if (lock) { @@ -256,6 +267,7 @@ static bool exec_openrc(pam_handle_t *pamh, const char *runlevel, bool lock) { PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *runlevel = argc > 0 ? runlevel = argv[0] : "default"; + int ret = PAM_SUCCESS; (void)flags; setenv("EINFO_LOG", "openrc-pam", 1); @@ -263,17 +275,18 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, cons if (exec_openrc(pamh, runlevel, true)) { elog(LOG_INFO, "Openrc session opened"); - unsetenv("EINFO_LOG"); - return PAM_SUCCESS; } else { elog(LOG_ERR, "Failed to open session"); - unsetenv("EINFO_LOG"); - return PAM_SESSION_ERR; + ret = PAM_SESSION_ERR; } + + unsetenv("EINFO_LOG"); + return ret; } PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *runlevel = argc > 1 ? argv[1] : "none"; + int ret = PAM_SUCCESS; (void)flags; setenv("EINFO_LOG", "openrc-pam", 1); @@ -281,11 +294,11 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, con if (exec_openrc(pamh, runlevel, false)) { elog(LOG_INFO, "Openrc session closed"); - unsetenv("EINFO_LOG"); - return PAM_SUCCESS; } else { elog(LOG_ERR, "Failed to close session"); - unsetenv("EINFO_LOG"); - return PAM_SESSION_ERR; + ret = PAM_SESSION_ERR; } + + unsetenv("EINFO_LOG"); + return ret; } |