aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/meson.build1
-rw-r--r--src/openrc-pam/meson.build11
-rw-r--r--src/openrc-pam/openrc-pam.c72
-rw-r--r--src/shared/misc.c2
4 files changed, 86 insertions, 0 deletions
diff --git a/src/meson.build b/src/meson.build
index 76f6d8a1..e07e679b 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -16,6 +16,7 @@ subdir('mountinfo')
subdir('on_ac_power')
subdir('openrc')
subdir('openrc-init')
+subdir('openrc-pam')
subdir('openrc-run')
subdir('openrc-shutdown')
subdir('poweroff')
diff --git a/src/openrc-pam/meson.build b/src/openrc-pam/meson.build
new file mode 100644
index 00000000..a8536a97
--- /dev/null
+++ b/src/openrc-pam/meson.build
@@ -0,0 +1,11 @@
+if get_option('user_services') and get_option('pam') and pam_dep.found()
+ shared_library('pam_openrc',
+ ['openrc-pam.c'],
+ c_args : [cc_branding_flags, cc_user_services_flags],
+ dependencies : [pam_dep],
+ name_prefix : '',
+ link_with : [libeinfo, librc],
+ include_directories : [incdir, einfo_incdir, rc_incdir],
+ install : true,
+ install_dir : join_paths(libdir, 'security'))
+endif
diff --git a/src/openrc-pam/openrc-pam.c b/src/openrc-pam/openrc-pam.c
new file mode 100644
index 00000000..5b480836
--- /dev/null
+++ b/src/openrc-pam/openrc-pam.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <pwd.h>
+#include <security/pam_modules.h>
+#include <unistd.h>
+#include <librc.h>
+#include <stdbool.h>
+#include <syslog.h>
+#ifdef __FreeBSD__
+#include <security/pam_appl.h>
+#endif
+
+static bool exec_openrc(pam_handle_t *pamh, const char *runlevel) {
+ char *cmd = NULL;
+ const char *username;
+ struct passwd *pw = NULL;
+
+ if (pam_get_user(pamh, &username, "username:") != PAM_SUCCESS)
+ return false;
+ pw = getpwnam(username);
+ if (!pw)
+ return false;
+
+ xasprintf(&cmd, "openrc --user %s", runlevel);
+ switch (fork()) {
+ case 0:
+ setgid(pw->pw_gid);
+ setuid(pw->pw_uid);
+
+ execl(pw->pw_shell, "-", "-c", cmd, NULL);
+
+ free(cmd);
+ return false;
+ break;
+ case -1:
+ free(cmd);
+ return false;
+ break;
+ }
+ wait(NULL);
+ free(cmd);
+ return true;
+}
+
+PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
+ (void)flags;
+ (void)argc;
+ (void)argv;
+
+ setenv("RC_PAM_STARTING", "YES", true);
+ if (exec_openrc(pamh, "default")) {
+ unsetenv("RC_PAM_STARTING");
+ return PAM_SUCCESS;
+ } else {
+ unsetenv("RC_PAM_STARTING");
+ return PAM_SESSION_ERR;
+ }
+}
+
+PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
+ (void)flags;
+ (void)argc;
+ (void)argv;
+
+ setenv("RC_PAM_STOPPING", "YES", true);
+ if (exec_openrc(pamh, "none")) {
+ unsetenv("RC_PAM_STOPPING");
+ return PAM_SUCCESS;
+ } else {
+ unsetenv("RC_PAM_STOPPING");
+ return PAM_SESSION_ERR;
+ }
+}
diff --git a/src/shared/misc.c b/src/shared/misc.c
index 6970513f..9b40ce36 100644
--- a/src/shared/misc.c
+++ b/src/shared/misc.c
@@ -87,6 +87,8 @@ env_filter(void)
rc_stringlist_addu(env_allow, "XDG_RUNTIME_DIR");
rc_stringlist_addu(env_allow, "XDG_CONFIG_HOME");
rc_stringlist_addu(env_allow, "RC_USER_SERVICES");
+ rc_stringlist_addu(env_allow, "RC_PAM_STARTING");
+ rc_stringlist_addu(env_allow, "RC_PAM_STOPPING");
}
#endif
/*