diff options
author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-05-27 08:09:11 -0300 |
---|---|---|
committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-10-19 10:56:54 +0200 |
commit | e8f8f5ac734181ca313f0966f4397d9888baebd4 (patch) | |
tree | 2d92ce88f88342f5dd3e8282d8f3abd9282f1ceb | |
parent | 3f4314e7cb68efbbec648f06cf509c963750c03e (diff) |
openrc-pam: introduction of a PAM module for --user
the module gets the pam user and executes a new login shell, in order to
load the user's environment. this requires that the user's login shell
supports `-c` as an option to run a command. all shells that i know of
do.
Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
-rw-r--r-- | src/meson.build | 1 | ||||
-rw-r--r-- | src/openrc-pam/meson.build | 11 | ||||
-rw-r--r-- | src/openrc-pam/openrc-pam.c | 72 | ||||
-rw-r--r-- | src/shared/misc.c | 2 |
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 /* |