aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_xauth/pam_xauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_xauth/pam_xauth.c')
-rw-r--r--modules/pam_xauth/pam_xauth.c155
1 files changed, 85 insertions, 70 deletions
diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c
index 07ece647..a64ae89f 100644
--- a/modules/pam_xauth/pam_xauth.c
+++ b/modules/pam_xauth/pam_xauth.c
@@ -35,8 +35,10 @@
#include "config.h"
#include <sys/types.h>
-#include <sys/fsuid.h>
#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <errno.h>
#include <fnmatch.h>
#include <grp.h>
@@ -232,9 +234,11 @@ check_acl(pam_handle_t *pamh,
{
char path[PATH_MAX];
struct passwd *pwd;
- FILE *fp;
- int i, save_errno;
- uid_t euid;
+ FILE *fp = NULL;
+ int i, fd = -1, save_errno;
+ struct stat st;
+ PAM_MODUTIL_DEF_PRIVS(privs);
+
/* Check this user's <sense> file. */
pwd = pam_modutil_getpwnam(pamh, this_user);
if (pwd == NULL) {
@@ -250,12 +254,33 @@ check_acl(pam_handle_t *pamh,
"name of user's home directory is too long");
return PAM_SESSION_ERR;
}
- euid = geteuid();
- setfsuid(pwd->pw_uid);
- fp = fopen(path, "r");
+ if (pam_modutil_drop_priv(pamh, &privs, pwd))
+ return PAM_SESSION_ERR;
+ if (!stat(path, &st)) {
+ if (!S_ISREG(st.st_mode))
+ errno = EINVAL;
+ else
+ fd = open(path, O_RDONLY | O_NOCTTY);
+ }
save_errno = errno;
- setfsuid(euid);
- if (fp != NULL) {
+ if (pam_modutil_regain_priv(pamh, &privs)) {
+ if (fd >= 0)
+ close(fd);
+ return PAM_SESSION_ERR;
+ }
+ if (fd >= 0) {
+ if (!fstat(fd, &st)) {
+ if (!S_ISREG(st.st_mode))
+ errno = EINVAL;
+ else
+ fp = fdopen(fd, "r");
+ }
+ if (!fp) {
+ save_errno = errno;
+ close(fd);
+ }
+ }
+ if (fp) {
char buf[LINE_MAX], *tmp;
/* Scan the file for a list of specs of users to "trust". */
while (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -324,7 +349,7 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
struct passwd *tpwd, *rpwd;
int fd, i, debug = 0;
int retval = PAM_SUCCESS;
- uid_t systemuser = 499, targetuser = 0, euid;
+ uid_t systemuser = 499, targetuser = 0;
/* Parse arguments. We don't understand many, so no sense in breaking
* this into a separate function. */
@@ -486,10 +511,11 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
getuid(), getgid(),
xauth, "-f", cookiefile, "nlist", display,
NULL) == 0) {
- int save_errno;
#ifdef WITH_SELINUX
security_context_t context = NULL;
#endif
+ PAM_MODUTIL_DEF_PRIVS(privs);
+
/* Check that we got a cookie. If not, we get creative. */
if (((cookie == NULL) || (strlen(cookie) == 0)) &&
((strncmp(display, "localhost:", 10) == 0) ||
@@ -572,9 +598,10 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
}
/* Generate a new file to hold the data. */
- euid = geteuid();
- setfsuid(tpwd->pw_uid);
-
+ if (pam_modutil_drop_priv(pamh, &privs, tpwd)) {
+ retval = PAM_SESSION_ERR;
+ goto cleanup;
+ }
#ifdef WITH_SELINUX
if (is_selinux_enabled() > 0) {
struct selabel_handle *ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
@@ -592,33 +619,24 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
}
}
}
+#endif /* WITH_SELINUX */
fd = mkstemp(xauthority + sizeof(XAUTHENV));
- save_errno = errno;
+ if (fd < 0)
+ pam_syslog(pamh, LOG_ERR,
+ "error creating temporary file `%s': %m",
+ xauthority + sizeof(XAUTHENV));
+#ifdef WITH_SELINUX
if (context != NULL) {
free(context);
setfscreatecon(NULL);
}
-#else
- fd = mkstemp(xauthority + sizeof(XAUTHENV));
- save_errno = errno;
-#endif
-
- setfsuid(euid);
- if (fd == -1) {
- errno = save_errno;
- pam_syslog(pamh, LOG_ERR,
- "error creating temporary file `%s': %m",
- xauthority + sizeof(XAUTHENV));
+#endif /* WITH_SELINUX */
+ if (fd >= 0)
+ close(fd);
+ if (pam_modutil_regain_priv(pamh, &privs) || fd < 0) {
retval = PAM_SESSION_ERR;
goto cleanup;
}
- /* Set permissions on the new file and dispose of the
- * descriptor. */
- setfsuid(tpwd->pw_uid);
- if (fchown(fd, tpwd->pw_uid, tpwd->pw_gid) < 0)
- pam_syslog (pamh, LOG_ERR, "fchown: %m");
- setfsuid(euid);
- close(fd);
/* Get a copy of the filename to save as a data item for
* removal at session-close time. */
@@ -712,59 +730,56 @@ int
pam_sm_close_session (pam_handle_t *pamh, int flags UNUSED,
int argc, const char **argv)
{
- void *cookiefile;
int i, debug = 0;
- const char* user;
+ const char *user;
+ const void *data;
+ const char *cookiefile;
struct passwd *tpwd;
- uid_t unlinkuid, euid;
- unlinkuid = euid = geteuid ();
-
- if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS)
- pam_syslog(pamh, LOG_ERR, "error determining target user's name");
- else {
- tpwd = pam_modutil_getpwnam(pamh, user);
- if (!tpwd)
- pam_syslog(pamh, LOG_ERR, "error determining target user's UID");
- else
- unlinkuid = tpwd->pw_uid;
- }
+ PAM_MODUTIL_DEF_PRIVS(privs);
- /* Parse arguments. We don't understand many, so no sense in breaking
- * this into a separate function. */
+ /* Try to retrieve the name of a file we created when
+ * the session was opened. */
+ if (pam_get_data(pamh, DATANAME, &data) != PAM_SUCCESS)
+ return PAM_SUCCESS;
+ cookiefile = data;
+
+ /* Parse arguments. We don't understand many, so
+ * no sense in breaking this into a separate function. */
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug = 1;
continue;
}
- if (strncmp(argv[i], "xauthpath=", 10) == 0) {
+ if (strncmp(argv[i], "xauthpath=", 10) == 0)
continue;
- }
- if (strncmp(argv[i], "systemuser=", 11) == 0) {
+ if (strncmp(argv[i], "systemuser=", 11) == 0)
continue;
- }
- if (strncmp(argv[i], "targetuser=", 11) == 0) {
+ if (strncmp(argv[i], "targetuser=", 11) == 0)
continue;
- }
pam_syslog(pamh, LOG_WARNING, "unrecognized option `%s'",
argv[i]);
}
- /* Try to retrieve the name of a file we created when the session was
- * opened. */
- if (pam_get_data(pamh, DATANAME, (const void**) &cookiefile) == PAM_SUCCESS) {
- /* We'll only try to remove the file once. */
- if (strlen((char*)cookiefile) > 0) {
- if (debug) {
- pam_syslog(pamh, LOG_DEBUG, "removing `%s'",
- (char*)cookiefile);
- }
- /* NFS with root_squash requires non-root user */
- setfsuid (unlinkuid);
- unlink((char*)cookiefile);
- setfsuid (euid);
- *((char*)cookiefile) = '\0';
- }
+ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR,
+ "error determining target user's name");
+ return PAM_SESSION_ERR;
+ }
+ if (!(tpwd = pam_modutil_getpwnam(pamh, user))) {
+ pam_syslog(pamh, LOG_ERR,
+ "error determining target user's UID");
+ return PAM_SESSION_ERR;
}
+
+ if (debug)
+ pam_syslog(pamh, LOG_DEBUG, "removing `%s'", cookiefile);
+ if (pam_modutil_drop_priv(pamh, &privs, tpwd))
+ return PAM_SESSION_ERR;
+ if (unlink(cookiefile) == -1 && errno != ENOENT)
+ pam_syslog(pamh, LOG_WARNING, "Couldn't remove `%s': %m", cookiefile);
+ if (pam_modutil_regain_priv(pamh, &privs))
+ return PAM_SESSION_ERR;
+
return PAM_SUCCESS;
}