aboutsummaryrefslogtreecommitdiff
path: root/src/openrc-pam
diff options
context:
space:
mode:
Diffstat (limited to 'src/openrc-pam')
-rw-r--r--src/openrc-pam/openrc-pam.c83
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;
}