summaryrefslogtreecommitdiff
path: root/src/home/pam_systemd_home.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-05-07 11:01:42 +0200
committerLennart Poettering <lennart@poettering.net>2020-05-12 17:38:32 +0200
commit6c8428bb8bb7cbe18efa839093c842588cae5396 (patch)
tree0a1f1c522b2ec2ee9e8771ed4fc37283cc650d87 /src/home/pam_systemd_home.c
parentdbe7fff4765bad673d214c7e3db7bc088e163bea (diff)
downloadsystemd-6c8428bb8bb7cbe18efa839093c842588cae5396.tar.gz
pam_systemd_home: also store acquirement fd per user
We might pin a home through authentication and a different one through a session, all from the same PAM context, like sudo does. Hence also store the referencing fd keyed by the user name.
Diffstat (limited to 'src/home/pam_systemd_home.c')
-rw-r--r--src/home/pam_systemd_home.c91
1 files changed, 66 insertions, 25 deletions
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index 7a1d64854a..72ce062f54 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -62,27 +62,30 @@ static int parse_argv(
static int acquire_user_record(
pam_handle_t *handle,
+ const char *username,
UserRecord **ret_record) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
- const char *username = NULL, *json = NULL;
_cleanup_free_ char *homed_field = NULL;
+ const char *json = NULL;
int r;
assert(handle);
- r = pam_get_user(handle, &username, NULL);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
- return r;
- }
+ if (!username) {
+ r = pam_get_user(handle, &username, NULL);
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
+ return r;
+ }
- if (isempty(username)) {
- pam_syslog(handle, LOG_ERR, "User name not set.");
- return PAM_SERVICE_ERR;
+ if (isempty(username)) {
+ pam_syslog(handle, LOG_ERR, "User name not set.");
+ return PAM_SERVICE_ERR;
+ }
}
/* Let's bypass all IPC complexity for the two user names we know for sure we don't manage, and for
@@ -418,7 +421,9 @@ static int acquire_home(
bool do_auth = please_authenticate, home_not_active = false, home_locked = false;
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int acquired_fd = -1;
+ _cleanup_free_ char *fd_field = NULL;
const void *home_fd_ptr = NULL;
+ const char *username = NULL;
unsigned n_attempts = 0;
int r;
@@ -432,8 +437,27 @@ static int acquire_home(
* authenticates, while the other PAM hooks unset it so that they can a ref of their own without
* authentication if possible, but with authentication if necessary. */
+ r = pam_get_user(handle, &username, NULL);
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
+ return r;
+ }
+
+ if (isempty(username)) {
+ pam_syslog(handle, LOG_ERR, "User name not set.");
+ return PAM_SERVICE_ERR;
+ }
+
/* If we already have acquired the fd, let's shortcut this */
- r = pam_get_data(handle, "systemd-home-fd", &home_fd_ptr);
+ fd_field = strjoin("systemd-home-fd-", username);
+ if (!fd_field)
+ return pam_log_oom(handle);
+
+ r = pam_get_data(handle, fd_field, &home_fd_ptr);
+ if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA)) {
+ pam_syslog(handle, LOG_ERR, "Failed to retrieve PAM home reference fd: %s", pam_strerror(handle, r));
+ return r;
+ }
if (r == PAM_SUCCESS && PTR_TO_FD(home_fd_ptr) >= 0)
return PAM_SUCCESS;
@@ -441,7 +465,7 @@ static int acquire_home(
if (r != PAM_SUCCESS)
return r;
- r = acquire_user_record(handle, &ur);
+ r = acquire_user_record(handle, username, &ur);
if (r != PAM_SUCCESS)
return r;
@@ -557,7 +581,7 @@ static int acquire_home(
do_auth = true;
}
- r = pam_set_data(handle, "systemd-home-fd", FD_TO_PTR(acquired_fd), cleanup_home_fd);
+ r = pam_set_data(handle, fd_field, FD_TO_PTR(acquired_fd), cleanup_home_fd);
if (r < 0) {
pam_syslog(handle, LOG_ERR, "Failed to set PAM bus data: %s", pam_strerror(handle, r));
return r;
@@ -578,15 +602,27 @@ static int acquire_home(
return PAM_SUCCESS;
}
-static int release_home_fd(pam_handle_t *handle) {
+static int release_home_fd(pam_handle_t *handle, const char *username) {
+ _cleanup_free_ char *fd_field = NULL;
const void *home_fd_ptr = NULL;
int r;
- r = pam_get_data(handle, "systemd-home-fd", &home_fd_ptr);
- if (r == PAM_NO_MODULE_DATA || PTR_TO_FD(home_fd_ptr) < 0)
+ assert(handle);
+ assert(username);
+
+ fd_field = strjoin("systemd-home-fd-", username);
+ if (!fd_field)
+ return pam_log_oom(handle);
+
+ r = pam_get_data(handle, fd_field, &home_fd_ptr);
+ if (r == PAM_NO_MODULE_DATA || (r == PAM_SUCCESS && PTR_TO_FD(home_fd_ptr) < 0))
return PAM_NO_MODULE_DATA;
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to retrieve PAM home reference fd: %s", pam_strerror(handle, r));
+ return r;
+ }
- r = pam_set_data(handle, "systemd-home-fd", NULL, NULL);
+ r = pam_set_data(handle, fd_field, NULL, NULL);
if (r != PAM_SUCCESS)
pam_syslog(handle, LOG_ERR, "Failed to release PAM home reference fd: %s", pam_strerror(handle, r));
@@ -673,20 +709,25 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if (debug)
pam_syslog(handle, LOG_DEBUG, "pam-systemd-homed session end");
+ r = pam_get_user(handle, &username, NULL);
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
+ return r;
+ }
+
+ if (isempty(username)) {
+ pam_syslog(handle, LOG_ERR, "User name not set.");
+ return PAM_SERVICE_ERR;
+ }
+
/* Let's explicitly drop the reference to the homed session, so that the subsequent ReleaseHome()
* call will be able to do its thing. */
- r = release_home_fd(handle);
+ r = release_home_fd(handle, username);
if (r == PAM_NO_MODULE_DATA) /* Nothing to do, we never acquired an fd */
return PAM_SUCCESS;
if (r != PAM_SUCCESS)
return r;
- r = pam_get_user(handle, &username, NULL);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
- return r;
- }
-
r = pam_acquire_bus_connection(handle, &bus);
if (r != PAM_SUCCESS)
return r;
@@ -738,7 +779,7 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
if (r != PAM_SUCCESS)
return r;
- r = acquire_user_record(handle, &ur);
+ r = acquire_user_record(handle, NULL, &ur);
if (r != PAM_SUCCESS)
return r;
@@ -846,7 +887,7 @@ _public_ PAM_EXTERN int pam_sm_chauthtok(
if (r != PAM_SUCCESS)
return r;
- r = acquire_user_record(handle, &ur);
+ r = acquire_user_record(handle, NULL, &ur);
if (r != PAM_SUCCESS)
return r;