pam-tmpdir-0.11/0000755000000000000000000000000014723652051010400 5ustar pam-tmpdir-0.11/.gitignore0000644000000000000000000000010212421415340012350 0ustar *~ *.o configure m4/ build-aux/ Makefile.in aclocal.m4 install-sh pam-tmpdir-0.11/Makefile.am0000644000000000000000000000116014723431466012437 0ustar ACLOCAL_AMFLAGS = -I m4 libdir = $(PAMDIR) lib_LTLIBRARIES = pam_tmpdir.la pam_tmpdir_la_SOURCES = \ pam_tmpdir.c \ util.c pam_tmpdir_la_LIBADD = -lpam pam_tmpdir_la_LDFLAGS = -module -avoid-version -shared pkglibexec_PROGRAMS = pam-tmpdir-helper pam_tmpdir_helper_SOURCES = \ pam-tmpdir-helper.c \ util.c dist_man8_MANS = pam-tmpdir-helper.8 pam_tmpdir.8 AM_LDFLAGS = -no-install pam_tmpdir_helper_CFLAGS = $(AM_CFLAGS) pam_tmpdir_helper_LDADD = -lpam install-exec-hook: rm -f $(DESTDIR)$(PAMDIR)/*.la chown root $(DESTDIR)@HELPER_PATH@/pam-tmpdir-helper chmod u+s $(DESTDIR)@HELPER_PATH@/pam-tmpdir-helper pam-tmpdir-0.11/README0000644000000000000000000000226012421415340011247 0ustar This is pam_tmpdir, a module for (if needed) creating a secure directory for users' temporary files and setting TMP and TMPDIR. It is written by Tollef Fog Heen , and you may use this under the conditions of the GPL version 2, as noted in . I'd appreciate any bug reports, patches, suggestions etc. It is based on pam_env which in turn is based on pam_mail. To use this module, be sure to add a line like session optional pam_tmpdir.so to the services where you want to set $TMPDIR and $TMP. Note that using "optional" instead of "required" will allow users to login even if pam_tmpdir fails to create the safe tmpdir ($TMP and $TMPDIR will remain unset in this case). Using "required" will deny login if an error occurs while setting up the safe tmpdir, this could allow for a DoS attack if a malicious user gets the chance to create /tmp/user before pam_tmpdir does. The directory in which the users' temporary directories are created can be set using an entry in /etc/security/tmpdir.conf: tmpdir=/path/to/tmpdir pam_tmpdir will fail to create a safe tmpdir if this directory or any of its parents is group or world writable. pam-tmpdir-0.11/configure.ac0000644000000000000000000000173014723651656012701 0ustar dnl Process this file with autoconf to produce a configure script AC_INIT([pam-tmpdir],[0.11],[tfheen@err.no]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([pam_tmpdir.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign]) AC_PROG_CC LT_INIT AC_CHECK_HEADERS([security/pam_appl.h], [], [AC_MSG_ERROR([[PAM header files not found, install libpam-dev.]])]) AC_SUBST(PAMDIR, "\$(exec_prefix)/lib/security") AC_ARG_WITH(pam-dir, AS_HELP_STRING([--with-pam-dir=DIR],[Where to install PAM module [[PREFIX/lib/security]]]), [case "${withval}" in /*) PAMDIR="${withval}";; ./*|../*) AC_MSG_ERROR(Bad value for --with-pam-dir);; *) PAMDIR="\$(exec_prefix)/lib/${withval}";; esac]) AC_MSG_NOTICE([PAM installation path $PAMDIR]) AC_DEFINE([HELPER_PATH], [$libexecdir/$PACKAGE_NAME], [Path to helper binary]) AC_SUBST([HELPER_PATH], "\$(pkglibexecdir)") AC_CONFIG_FILES(Makefile) AC_OUTPUT pam-tmpdir-0.11/debian/0000755000000000000000000000000014723652233011624 5ustar pam-tmpdir-0.11/debian/README.Debian0000644000000000000000000000113512421415340013652 0ustar chroot considerations --------------------- If you're using tools that use chroots, please be aware that libpam-tmpdir only creates the directory and sets TMPDIR whenever a new PAM session is started. This means that some tools which do not reset TMPDIR, nor start a new PAM session might end up with TMPDIR pointing to a non-existent directory. An example of such as tool (when this is written) is pbuilder. To work around this, either enable a hook that unsets TMPDIR or one that creates TMPDIR if it is not present already. -- Tollef Fog Heen , Thu, 8 Mar 2012 22:42:03 +0100 pam-tmpdir-0.11/debian/changelog0000644000000000000000000001321014723652233013473 0ustar pam-tmpdir (0.11) unstable; urgency=medium * Fix up pam module location. Closes: #1088936 * Properly clean source tree. Closes: #1088937 * Run autoupdate to update configure.ac to more modern standards. -- Tollef Fog Heen Tue, 03 Dec 2024 19:57:31 +0100 pam-tmpdir (0.10) unstable; urgency=medium * Move pam-tmpdir-helper to /lib/pam-tmpdir. * Add Rules-Requires-Root: binary-targets * Ship tmpfiles snippet. Closes: #929495 * Add man page. Thanks for Curtis Hollibaugh for providing one. Closes: #715273 * Bump to debhelper compat level 13. * Fix up C pointer errors and include files. -- Tollef Fog Heen Mon, 02 Dec 2024 22:37:04 +0100 pam-tmpdir (0.09+nmu1) unstable; urgency=medium * Non-maintainer upload. * Install into /usr (DEP17 M2) (Closes: #1061239) * Update lintian override to currently correct tag and format. -- Chris Hofstaedtler Mon, 22 Apr 2024 01:48:11 +0200 pam-tmpdir (0.09) unstable; urgency=low * Add README.Debian explaining a bit about how pam-tmpdir works. * Drop Steve Kemp from Uploaders as he's unfortunately no longer active in Debian. * Update to dh compat level 9 * Switch to dh. * Various cleanups * Switch upstream build system to automake * Multiarchify * Add TEMP and TEMPDIR to the list of environment variables we check. Closes: #652607 * Make this a native package to get around various dpkg silliness. * Drop debian/dirs, it is no longer needed. -- Tollef Fog Heen Thu, 08 Mar 2012 22:44:21 +0100 pam-tmpdir (0.08-1) unstable; urgency=low * New upstream version with Steve's changes. * Clean out some junk in debian/rules (mostly comments) * Integrate with new libpam-runtime, thanks to Sam Morris for patch. (Closes: #521576) * Refer explicitly to GPLv2 in copyright file. * Update to debhelper v7 (no changes but debian/compat needed) * Update to policy version 3.8.2, no changes needed. -- Tollef Fog Heen Sat, 08 Aug 2009 15:49:06 +0200 pam-tmpdir (0.07-3) unstable; urgency=medium * Avoid failure to build from source by updating the 'extraclean' rule. (Closes: #471215) -- Steve Kemp Tue, 1 Apr 2008 19:50:01 +0000 pam-tmpdir (0.07-2) unstable; urgency=low * Avoid crashing on malformed configuration file. (Closes: #431371) * Update the configuration file to match documentation. - /etc/security/tmpdir.conf is used not /etc/pam-tmpdir.conf. (Closes: #379832) * Misc: - Updated standards version to 3.7.3: - Updated compatibility level to 4. - Don't ignore error in 'make clean' - Updated copyright file to be explicit, and pass lintian test. - Added lintian override for the setuid helper binary. - Added myself as an uploader. -- Steve Kemp Mon, 14 Mar 2008 00:11:00 +0000 pam-tmpdir (0.07-1) unstable; urgency=low * New upstream release - Links with PAM (closes: #373634) - Mentions tmpdir.conf in README (closes: #338912) - Sets and restores SIGCHLD handles when calling helper (closes: #355205) - Don't freak out if the configuration file is in an unsafe place, just use the default path then. (Closes: #340415) -- Tollef Fog Heen Mon, 17 Jul 2006 12:06:15 +0200 pam-tmpdir (0.06-1) unstable; urgency=low * New upstream release - Fix minor typo in configure.in which caused the package to fail to build from source. Also rename to configure.ac. Closes #355145 -- Tollef Fog Heen Tue, 7 Mar 2006 11:44:30 +0100 pam-tmpdir (0.05-2) unstable; urgency=low * Use exit 1 instead of exit 0 in x{malloc,realloc}. Thanks to Ethan Benson for spotting this. * Change default configuration file to /etc/security/tmpdir.conf, again thanks to Ethan Benson for spotting this. -- Tollef Fog Heen Fri, 26 Dec 2003 14:28:32 +0100 pam-tmpdir (0.05-1) unstable; urgency=low * New upstream version - SYSUSRTMP is now configurable (closes: #204571) -- Tollef Fog Heen Tue, 23 Dec 2003 16:08:19 +0100 pam-tmpdir (0.04-3) unstable; urgency=low * Mkdir then lstat, not the other way around. (closes: #202661) -- Tollef Fog Heen Sun, 5 Jan 2003 13:40:47 +0100 pam-tmpdir (0.04-2) unstable; urgency=low * redo the make_tmp_directory function, in order to work with both the new, broken ssh without breaking stuff like login. (closes: #151107) -- Tollef Fog Heen Sun, 30 Jun 2002 00:57:24 +0200 pam-tmpdir (0.04-1) unstable; urgency=low * New upstream version with SUID helper to work with new fucked SSH. (closes: #150935, #150899). * Tweaked the copyright file a little bit -- pam-tmpdir is under GPL v2, not GPL v2 or later. * Add man page for helper application. -- Tollef Fog Heen Tue, 25 Jun 2002 19:09:05 +0200 pam-tmpdir (0.03-1) unstable; urgency=medium * New upstream release with some potential security fixes. Thanks to Ethan Benson -- Tollef Fog Heen Mon, 4 Feb 2002 20:04:31 +0100 pam-tmpdir (0.02-1) unstable; urgency=low * Fix compile problem on Hurd (closes: #106915) -- Tollef Fog Heen Mon, 30 Jul 2001 00:27:11 +0200 pam-tmpdir (0.01-2) unstable; urgency=low * Clean up properly after us (closes: #101470) * chmod +x configure in debian/rules (closes: #101440, #101383) * Fix section -- Tollef Fog Heen Sun, 24 Jun 2001 08:00:07 +0200 pam-tmpdir (0.01-1) unstable; urgency=low * Initial Release. -- Tollef Fog Heen Wed, 13 Jun 2001 23:03:56 +0200 pam-tmpdir-0.11/debian/control0000644000000000000000000000145014723431466013232 0ustar Source: pam-tmpdir Section: admin Priority: optional Maintainer: Tollef Fog Heen Build-Depends: debhelper (>= 13), libpam-dev, dh-autoreconf Standards-Version: 3.8.2 Rules-Requires-Root: binary-targets X-DH-Compat: 13 Package: libpam-tmpdir Architecture: any Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-runtime (>= 1.0.1-6) Description: automatic per-user temporary directories Many programs use $TMPDIR for storing temporary files. Not all of them are good at securing the permissions of those files. libpam-tmpdir sets $TMPDIR and $TMP for PAM sessions and sets the permissions quite tight. This helps system security by having an extra layer of security, making such symlink attacks and other /tmp based attacks harder or impossible pam-tmpdir-0.11/debian/copyright0000644000000000000000000000056313134171142013551 0ustar This package was debianized by Tollef Fog Heen on Wed, 30 May 2001 07:49:27 +0200. Authors: Tollef Fog Heen Copyright 2001-2008 Tollef Fog Heen The software is licensed under the terms of the GNU Public License, version 2. The complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL-2 file. pam-tmpdir-0.11/debian/docs0000644000000000000000000000000712421415337012467 0ustar README pam-tmpdir-0.11/debian/libpam-tmpdir.install0000644000000000000000000000016612421415340015745 0ustar debian/pam-configs/tmpdir /usr/share/pam-configs debian/lintian-overrides/libpam-tmpdir /usr/share/lintian/overrides pam-tmpdir-0.11/debian/libpam-tmpdir.manpages0000644000000000000000000000001514723424522016074 0ustar pam_tmpdir.8 pam-tmpdir-0.11/debian/libpam-tmpdir.tmpfiles0000644000000000000000000000024314723423400016121 0ustar # # Ensure /tmp/user exists with strict permissions. # # If you want more lenient permissions, feel free to change this to 0755. d /tmp/user 0711 root root - pam-tmpdir-0.11/debian/lintian-overrides/0000755000000000000000000000000014723423661015263 5ustar pam-tmpdir-0.11/debian/lintian-overrides/libpam-tmpdir0000644000000000000000000000011714723423661017746 0ustar libpam-tmpdir: elevated-privileges 4755 root/root [usr/sbin/pam-tmpdir-helper] pam-tmpdir-0.11/debian/pam-configs/0000755000000000000000000000000012421415340014014 5ustar pam-tmpdir-0.11/debian/pam-configs/tmpdir0000644000000000000000000000017612421415340015242 0ustar Name: per-user temporary directories Default: yes Priority: 0 Session-Type: Additional Session-Final: optional pam_tmpdir.so pam-tmpdir-0.11/debian/postinst0000644000000000000000000000043412421415340013420 0ustar #! /bin/sh -e # Move /etc/pam_tmpdir.conf to /etc/security/tmpdir.conf, since that's # the proper place if [ -e "/etc/pam-tmpdir.conf" -a ! -e /etc/security/tmpdir.conf ]; then mv /etc/pam-tmpdir.conf /etc/security/tmpdir.conf fi pam-auth-update --package #DEBHELPER# exit 0 pam-tmpdir-0.11/debian/prerm0000644000000000000000000000010612421415340012656 0ustar #! /bin/sh -e pam-auth-update --package --remove tmpdir #DEBHELPER# pam-tmpdir-0.11/debian/rules0000755000000000000000000000054514723651122012704 0ustar #!/usr/bin/make -f # export DH_VERBOSE=1 DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) %: dh $@ --with autoreconf override_dh_auto_configure: dh_auto_configure -- --with-pam-dir=/usr/lib/$(DEB_HOST_MULTIARCH)/security override_dh_fixperms: dh_fixperms chmod u+s debian/libpam-tmpdir/usr/libexec/pam-tmpdir/pam-tmpdir-helper pam-tmpdir-0.11/debian/tests/0000755000000000000000000000000014723431551012764 5ustar pam-tmpdir-0.11/debian/tests/control0000644000000000000000000000012414723431551014364 0ustar Tests: test-env test-directory-creation Restrictions: needs-root Depends: @, strace pam-tmpdir-0.11/debian/tests/test-directory-creation0000644000000000000000000000017314723431551017473 0ustar #! /bin/bash su - root -c 'true' if ! [ -d /tmp/user/0 ]; then echo "TMP directory not created" exit 1 fi exit 0 pam-tmpdir-0.11/debian/tests/test-env0000644000000000000000000000022214723431551014450 0ustar #! /bin/bash T="$(su - root -c 'echo $TMP')" if [ "$T" != "/tmp/user/0" ]; then echo "Unexpected value for TMP: '$T'" >&2 exit 1 fi exit 0 pam-tmpdir-0.11/install-sh0000755000000000000000000001273612421415337012412 0ustar #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 pam-tmpdir-0.11/pam-tmpdir-helper.80000644000000000000000000000170512421415340014012 0ustar .TH PAM-TMPDIR-HELPER 8 " Jun 25 2002" "PAM-TMPDIR 0.04" "pam-tmpdir" .SH NAME \fBpam-tmpdir-helper\fR \- create safe temporary directory .SH SYNOPSIS .SH DESCRIPTION A helper binary for the pam_tmpdir module, pam-tmpdir-helper is invoked to create a secure temporary directory for the invoking user. It is quite simple and is called on behalf on the user by the session component of the pam_tmpdir module. It is not harmful to call it by hand, but will not give out any diagnostics, nor error messages, apart from its return value. It logs to syslog. .SH USAGE This program is not intended to be called directly by users and will log to syslog if it is called improperly (i.e., by some one trying exploit it). .SH COPYRIGHT Copyright \(co 2002-2012 Tollef Fog Heen . .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. pam-tmpdir-0.11/pam-tmpdir-helper.c0000644000000000000000000000766414723431466014115 0ustar /* pam_tmpdir module, based on pam_env which in turn was based on pam_mail */ /* * $Id: pam_env.c,v 1.3 1999/11/08 05:46:53 morgan Exp $ * * Written by Tollef Fog Heen 2001-02-03 * * Based on pam_env * Written by Dave Kinchlea 1997/01/31 * Inspired by Andrew Morgan #include #include #include #include #include #include #include #include #include #include #include "util.h" static int make_tmp_directory() { int ret; char *user_tmpdir; struct stat statbuf; mode_t old_umask; char *tmpdir = get_tmp_dir(); if (tmpdir == NULL) { return 1; } /* We want 100% control of permissions */ old_umask = umask(0000); /* Create $tmpdir */ ret = mkdir(tmpdir,0711); /* Check whether the mkdir succeeded */ if (ret == -1 && errno != EEXIST) { _log_err(LOG_NOTICE, "mkdir %s failed: %s\n", tmpdir, strerror(errno)); free(tmpdir); return 1; } else if (ret != -1) { if (chown(tmpdir, 0, 0) == -1) { _log_err(LOG_NOTICE, "chown 0:0 %s failed: %s\n", tmpdir, strerror(errno)); free(tmpdir); return 1; } } umask(old_umask); /* $tmpdir should now exist. Make sure it is Check that $tmpdir is acceptable */ ret = lstat(tmpdir,&statbuf); if (ret == -1) { _log_err(LOG_NOTICE, "%s", "lstat %s failed: %s\n", tmpdir, strerror(errno)); return 1; } else if (statbuf.st_uid != 0) { /* Somebody else than root has grabbed /tmp/user. Bad, bad, bad. */ _log_err(LOG_ERR, "%s is owned by uid %d instead of root " "(uid 0). Failed to create safe $TMPDIR\n", tmpdir, statbuf.st_uid); free(tmpdir); return 1; } else if (!S_ISDIR(statbuf.st_mode)) { _log_err(LOG_NOTICE, "%s is not a directory. Failed to create safe " "$TMPDIR\n", tmpdir); free(tmpdir); return 1; } else if ((statbuf.st_mode & S_IWGRP) || (statbuf.st_mode & S_IWOTH)) { _log_err(LOG_NOTICE, "%s is group or world writable. " "Failed to create safe $TMPDIR\n", tmpdir); free(tmpdir); return 1; } else if (!(statbuf.st_mode & S_IXOTH)) { _log_err(LOG_NOTICE,"%s is not world searchable. " "Failed to create safe $TMPDIR\n", tmpdir); free(tmpdir); return 1; } if (asprintf(&user_tmpdir, "%s/%d",tmpdir,getuid()) == -1) { return 1; } /* Create user tmp dir */ ret = mkdir(user_tmpdir,0700); if (ret == -1 && errno != EEXIST) { _log_err(LOG_NOTICE, "mkdir %s failed: %s\n", user_tmpdir, strerror(errno)); return 1; } else if (ret != -1) { if (chown(user_tmpdir, getuid(), getgid()) == -1) { _log_err(LOG_NOTICE, "chown %d:%d %s failed: %s\n", getuid(), getgid(), user_tmpdir, strerror(errno)); return 1; } } ret = lstat(user_tmpdir,&statbuf); if (ret == -1) { _log_err(LOG_NOTICE, "lstat %s failed: %s\n", user_tmpdir, strerror(errno)); return 1; } else if (statbuf.st_uid != getuid()) { _log_err(LOG_NOTICE, "%s owned by uid %d instead of uid %d. " "Failed to create safe $TMPDIR\n", user_tmpdir, statbuf.st_uid, getuid()); return 1; } else if (!S_ISDIR(statbuf.st_mode)) { _log_err(LOG_NOTICE, "%s is not a directory. Failed to create safe $TMPDIR\n", user_tmpdir); return 1; } if ((statbuf.st_mode & S_IWGRP) || (statbuf.st_mode & S_IWOTH)) { _log_err(LOG_NOTICE, "Warning: %s is group or world writable. " "Changing permissions to 0700\n", user_tmpdir); if (chmod(user_tmpdir, 0700) == -1) { _log_err(LOG_NOTICE, "chmod 0700 %s failed: %s\n", user_tmpdir, strerror(errno)); return 1; } } return 0; } int main(int argc, char **argv) { (void)argc; (void)argv; return make_tmp_directory(); } pam-tmpdir-0.11/pam_tmpdir.80000644000000000000000000000305314723424076012632 0ustar .TH PAM_TMPDIR 8 .SH NAME \fBpam_tmpdir\fP \- PAM module for creating a secure directory for users' temporary files .SH SYNOPSIS \fBpam_tmpdir.so\fP .SH DESCRIPTION This module can be plugged into the \fBsession\fP stack of a given service to provide secure, per-user directories for temporary files. .SH OPTIONS The directory in which the users' temporary directories are created can be set using an entry in /etc/security/tmpdir.conf: .EX tmpdir=/path/to/tmpdir .EE The default is /tmp/user. .SH MODULE TYPES PROVIDED Although this is intended to be used with the \fBsession\fP module type, it also provides \fBaccount\fP, \fBauth\fP, and \fBpassword\fP module types. .SH RETURN VALUES .IP PAM_SUCCESS The temporary directory was successfully created. .IP PAM_ABORT An error occurred when attempting to create the temporary directory. .IP PAM_SERVICE_ERR An internal error occurred. .SH EXAMPLES .PP To allow users to login even if pam_tmpdir fails to create a safe tmpdir: .IP .EX session optional pam_tmpdir.so .EE .PP To deny login if an error occurs while setting up the safe tmpdir: .IP .EX session required pam_tmpdir.so .EE .PP \fINOTE\fP: This could allow for a DoS attack if a malicious user creates /tmp/user before pam_tmpdir does. .SH SEE ALSO \fIpam-tmpdir-helper\fP\|(8) .SH AUTHOR Tollef Fog Heen .SH COPYRIGHT Copyright \(co 2002-2012 Tollef Fog Heen . .BR This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. pam-tmpdir-0.11/pam_tmpdir.c0000644000000000000000000001215714723431551012706 0ustar /* pam_tmpdir module, based on pam_env which in turn was based on pam_mail */ /* * $Id: pam_env.c,v 1.3 1999/11/08 05:46:53 morgan Exp $ * * Written by Tollef Fog Heen 2001-02-03 * * Based on pam_env * Written by Dave Kinchlea 1997/01/31 * Inspired by Andrew Morgan #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module * but strongly encouraged generally) it is used to instruct the * modules include file to define the function prototypes. */ #define PAM_SM_SESSION /* This is primarily a AUTH_SESSION module */ #define PAM_SM_AUTH /* But I like to be friendly */ #define PAM_SM_PASSWORD /* "" */ #define PAM_SM_ACCOUNT /* "" */ #include #include #define PAM_TMPDIR_HELPER "/usr/libexec/pam-tmpdir/pam-tmpdir-helper" static int set_environment(pam_handle_t *pamh); static int make_tmp_directory(pam_handle_t *pamh); int get_user_id(pam_handle_t *pamh, uid_t *uid) { const void *username; struct passwd* user_entry; int r; r = pam_get_item(pamh, PAM_USER, &username); if (r != PAM_SUCCESS) { _log_err(LOG_WARNING, "could not get PAM user"); return -1; } user_entry = getpwnam(username); *uid = user_entry->pw_uid; return 0; } /* argument parsing */ #define PAM_DEBUG_ARG 0x01 #define PAM_NEW_CONF_FILE 0x02 #define PAM_ENV_SILENT 0x04 #define PAM_NEW_ENV_FILE 0x10 static int set_environment(pam_handle_t *pamh) { char *buf; char *tmpdir = get_tmp_dir(); char *envs[] = { "TMP", "TMPDIR", "TEMP", "TEMPDIR", NULL }; uid_t u; if (get_user_id(pamh, &u) != 0) { free(tmpdir); return -1; } for (int i = 0; envs[i]; i++) { asprintf(&buf, "%s=%s/%d", envs[i], tmpdir, u); pam_putenv(pamh, buf); free(buf); } free(tmpdir); return 0; } /* --- authentication management functions (only) --- */ static int make_tmp_directory(pam_handle_t *pamh) { int ret = 0; int status; pid_t pid; struct sigaction old, new; new.sa_handler = SIG_DFL; sigemptyset(&new.sa_mask); new.sa_flags = 0; /* save old signal handler */ ret = sigaction(SIGCHLD, &new, &old); if (ret == -1) { _log_err(LOG_WARNING, "could not save SIGCHLD handler"); return 1; } /* Do fork and exec by hand.. */ pid = fork(); if (!pid) { /* child */ if (geteuid() == 0) { uid_t u; if (get_user_id(pamh, &u) != 0) { exit(1); } if (setuid(u) != 0) { exit(1); } } execl(PAM_TMPDIR_HELPER,PAM_TMPDIR_HELPER,NULL); exit(1); } ret = waitpid(pid, &status, 0); if (ret == -1) { _log_err(LOG_ERR, "error waiting for helper binary (%d)\n", errno); return 1; } /* restore old signal handler */ ret = sigaction(SIGCHLD, &old, NULL); if (ret == -1) { _log_err(LOG_WARNING, "could not restore SIGCHLD handler"); return 1; } return WEXITSTATUS(status); } PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; return PAM_IGNORE; } PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; if (make_tmp_directory(pamh) == 0) { set_environment(pamh); return PAM_SUCCESS; } else { return PAM_ABORT; } } PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; _log_err(LOG_NOTICE, "pam_sm_acct_mgmt called inappropriatly"); return PAM_SERVICE_ERR; } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; if (make_tmp_directory(pamh) == 0) { set_environment(pamh); return PAM_SUCCESS; } else { return PAM_ABORT; } } PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; D(("Called and Exit")); return PAM_SUCCESS; } PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)pamh; (void)flags; (void)argc; (void)argv; _log_err(LOG_NOTICE, "pam_sm_chauthtok called inappropriatly"); return PAM_SERVICE_ERR; } #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_env_modstruct = { "pam_tmpdir", pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt, pam_sm_open_session, pam_sm_close_session, pam_sm_chauthtok, }; #endif /* end of module definition */ pam-tmpdir-0.11/util.c0000644000000000000000000000755014723431466011535 0ustar #include "util.h" #define DEFAULT_SYSUSRTMP "/tmp/user" #define CONFIG_FILE "/etc/security/tmpdir.conf" /* Standard implementation of xrealloc -- exit if anything goes wrong */ void *xrealloc(void *ptr, size_t size) { void *r = realloc(ptr, size); if (r == NULL) { _log_err(LOG_ERR, "Out of memory in xrealloc"); exit(0); } return r; } /* Standard implementation of xmalloc -- exit if anything goes wrong */ void *xmalloc(size_t size) { void *r = malloc(size); if (r == NULL) { _log_err(LOG_ERR, "Out of memory in xmalloc"); exit(0); } return r; } /* Why doesn't libc have a method to read a line from a file, similar to python's f.readline()? This is an implementation. */ char *freadline(FILE *stream) { char buf[512]; size_t alloc = 0; char *ret = NULL; char *t; t = fgets(buf, sizeof(buf), stream); if (t == NULL) { return NULL; } ret = xmalloc(sizeof(buf)); strcpy(ret, buf); t = fgets(buf, sizeof(buf), stream); return ret; } int check_dir_ok(char *path) { struct stat statbuf; int ret; ret = lstat(path,&statbuf); if (ret == -1) { _log_err(LOG_NOTICE, "%s", "lstat %s failed: %s\n", path, strerror(errno)); return 1; } else if (statbuf.st_uid != 0) { /* Somebody else than root has grabbed the dir. Bad, bad, bad. */ _log_err(LOG_ERR, "%s is owned by uid %d instead of root " "(uid 0).\n", path, statbuf.st_uid); return 1; } else if (!S_ISDIR(statbuf.st_mode)) { _log_err(LOG_NOTICE, "%s is not a directory.\n", path); return 1; } else if ((statbuf.st_mode & S_IWGRP) || (statbuf.st_mode & S_IWOTH)) { _log_err(LOG_NOTICE, "%s is group or world writable. ", path); return 1; } return 0; } int check_path(const char *path) { char *p = strdup(path); char *tmp; /* special-case /, since it should end with / */ if (check_dir_ok("/") != 0) { free(p); return 1; } tmp = strchr(p+1,'/'); /* +1 so we don't change the initial / :) */ if (tmp != NULL) { *tmp = '\0'; } while (tmp != NULL) { if (check_dir_ok(p) != 0) { free(p); return 1; } *tmp = '/'; tmp = strchr(tmp+1,'/'); } /* One last check for the full path */ if (check_dir_ok(p) != 0) { free(p); return 1; } free(p); return 0; } char *get_tmp_dir() { char *line; FILE *conf; char *confdir = dirname(strdup(CONFIG_FILE)); char *tmp; /* Start paranoia checks */ if (check_path(confdir) != 0) { /* Can't trust confdir, just return DEFAULT_SYSUSRTMP */ return strdup(DEFAULT_SYSUSRTMP); } /* Ok, paranoia checks over, let's open the file and parse it, then */ conf = fopen(CONFIG_FILE,"r"); if (conf == NULL) { /* Fallback */ return strdup(DEFAULT_SYSUSRTMP); } line = freadline(conf); while (line) { char *key, *value; if ((line[0] == '#') || (strchr(line, '=') == NULL)) { free(line); line = freadline(conf); continue; } tmp = strchr(line, '='); *tmp = '\0'; key = line; value = tmp+1; /* chomp */ if (value[strlen(value)-1] == '\n') { value[strlen(value)-1] = '\0'; } if (strcmp(key, "tmpdir") == 0) { value = strdup(value); free(line); return value; } /* Cleanup */ free(line); line = freadline(conf); } /* Fallback */ return strdup(DEFAULT_SYSUSRTMP); } /* some syslogging */ void _log_err(int err, const char *format, ...) { va_list args; va_start(args, format); openlog("PAM_tmpdir", LOG_CONS|LOG_PID, LOG_AUTH); vsyslog(err, format, args); va_end(args); closelog(); } const char *get_homedir(pam_handle_t *pamh) { const void *username; struct passwd* user_entry; int r; r = pam_get_item(pamh, PAM_USER, &username); if (r != PAM_SUCCESS) { _log_err(LOG_WARNING, "could not get PAM user"); return NULL; } user_entry = getpwnam(username); return user_entry->pw_dir; } pam-tmpdir-0.11/util.h0000644000000000000000000000113014723431466011526 0ustar #ifndef _PAM_TMPDIR_UTIL_H_ #define _PAM_TMPDIR_UTIL_H_ #include #include #include #include #include #include #include #include #include #include #include #include void *xrealloc(void *ptr, size_t size); void *xmalloc(size_t size); char *freadline(FILE *stream); int check_dir_ok(char *path); int check_path(const char *path); char *get_tmp_dir(); void _log_err(int err, const char *format, ...); const char *get_homedir(pam_handle_t *pamh); #endif