ports/contrib (3.6): pam_xdg: strip to minimum (cannot track sessions via PAM), thus graceful
commit f2193cf1ac2451cba1777bde2993065d90972f09 Author: Steffen Nurpmeso <steffen@sdaoden.eu> Date: Sun Jan 31 01:39:17 2021 +0100 pam_xdg: strip to minimum (cannot track sessions via PAM), thus graceful diff --git a/pam_xdg/.signature b/pam_xdg/.signature index ee0895692..06ecf7a22 100644 --- a/pam_xdg/.signature +++ b/pam_xdg/.signature @@ -1,7 +1,7 @@ untrusted comment: verify with /etc/ports/contrib.pub -RWSagIOpLGJF3yVeUzlfQ7+UJq2gIuabqKJqhiWq7h2/UY5x8mlWVY7NEag9ndV9ypuodnfpLrP0QWzNjqO3eRJ1b5zTk3MRnAs= -SHA256 (Pkgfile) = e1b2ba87fd768518b4f81f3f9fb1fcce6780b2538cded18600564532e86f6a05 +RWSagIOpLGJF3/opxnSlpIKUNMt7/zCoADPQ4PYlOmbd2GckIrSxOZvjqNNRaw5n+mhVd/iOl35BH6C2CIKF12kK6df2J7zZ4Q8= +SHA256 (Pkgfile) = ac39f667ad9c2778b25753a6265ef2705335afb9b5cde1f70d9cb86f9ee22076 SHA256 (.footprint) = 56d789b652e6167f5fb93e1e6d48243e13f598c6d9a72705a8e54a003574ba31 -SHA256 (pam_xdg.c) = 9125ac3749b087f78844953a1a43790055a62efa0b8c25bd8766e35b061ca58c -SHA256 (pam_xdg.8) = 0f19e9f2437c6d0cb24465798ded6d6a3b2be07c012ee611648a4e4f1a21bbf1 +SHA256 (pam_xdg.c) = 81bfedeb798bc63d33f2b44874df0d796b439e93876a4a41f94d1ee26a001c38 +SHA256 (pam_xdg.8) = 2929bcd6655d28127d386215d3d8c4fed6744b65c4866ac7e49d54cb438d9133 SHA256 (makefile) = 2466f499c3e84fd821176371fa9ff78143bf94b9ec09fd9e654b35613e4ead7d diff --git a/pam_xdg/Pkgfile b/pam_xdg/Pkgfile index 71c42bd5e..b798857b7 100644 --- a/pam_xdg/Pkgfile +++ b/pam_xdg/Pkgfile @@ -3,7 +3,7 @@ # Maintainer: Steffen Nurpmeso, steffen at sdaoden dot eu name=pam_xdg -version=20210130 +version=20210131 release=1 source=($name.c $name.8 makefile) diff --git a/pam_xdg/pam_xdg.8 b/pam_xdg/pam_xdg.8 index 013fb7ea1..67c62ad81 100644 --- a/pam_xdg/pam_xdg.8 +++ b/pam_xdg/pam_xdg.8 @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. . -.Dd January 30, 2021 +.Dd January 31, 2021 .Dt PAM_XDG 8 .Os . @@ -35,7 +35,7 @@ .Sh DESCRIPTION . .Nm -is a PAM module that manages creation and deletion of the +is a PAM module that manages creation of the .Ev XDG_RUNTIME_DIR directory, as well as injection of environment variables denoting all directories specified by the @@ -44,19 +44,17 @@ spec/\:basedir-\:spec-\:latest.html "XDG Base Directory Specification" into user sessions. . .Pp -When linked into the PAM system, the runtime directory will be created as -.Ql /run/user/`id -u` -once a user creates his or her first login session, and it will be -removed recursively once the last such session ends. +When linked into the PAM session system the runtime directory will be +created once a user creates his or her first login session. Unless .Ar rundir -was given all XDG related environment variables will be created in the -user session with their default or computed values, otherwise only +was given all XDG related environment variables will be created in all +user sessions with their default or computed values, otherwise only .Ev XDG_RUNTIME_DIR . If .Ar notroot -was given the module will bypass itself for root account logins, that -is, no actions will be performed. +was given the module will bypass itself for root account logins and +perform no actions for root. . .Pp In order to make use of this script, place the following in the control diff --git a/pam_xdg/pam_xdg.c b/pam_xdg/pam_xdg.c index a2c56cdfe..1ed589727 100644 --- a/pam_xdg/pam_xdg.c +++ b/pam_xdg/pam_xdg.c @@ -1,14 +1,12 @@ /*@ pam_xdg - manage XDG Base Directories (runtime dir life time, environment). - *@ Create /run/user/`id -u` when the first session is opened, and remove it - *@ again once the last is closed. + *@ Create /run/user/`id -u` when the first session is opened. *@ It also creates according XDG_RUNTIME_DIR etc. environment variables in the *@ user sessions, except when given the "runtime" option, in which case it *@ only creates XDG_RUNTIME_DIR and not the others. *@ Place for example in /etc/pam.d/common-session one of the following: *@ session options pam_xdg.so [runtime] [notroot] - *@ Notes: - effectively needs ISO C99 as it uses strtoull(3). - *@ - according to XDG Base Directory Specification, v0.7. - *@ - Linux. + *@ Notes: - according to XDG Base Directory Specification, v0.7. + *@ - Linux-only (i think). * * Copyright (c) 2021 Steffen Nurpmeso <steffen@sdaoden.eu>. * SPDX-License-Identifier: ISC @@ -37,13 +35,9 @@ /* */ #define a_XDG "pam_xdg" -#define a_RUNTIME_DIR_OUTER "/run" /* This must exist already */ +#define a_RUNTIME_DIR_OUTER "/run" /* This must exist already */ #define a_RUNTIME_DIR_BASE "user" /* We create this as necessary, thus. */ - -#define a_LOCK_FILE "." a_XDG ".lck" -#define a_LOCK_TRIES 10 - -#define a_DAT_FILE "." a_XDG ".dat" +#define a_RUNTIME_DIR_BASE_MODE 0755 /* 0711? */ /* >8 -- 8< */ @@ -55,13 +49,10 @@ #include <sys/stat.h> #include <sys/types.h> -#include <sys/wait.h> #include <errno.h> #include <fcntl.h> -#include <limits.h> #include <pwd.h> -#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -82,23 +73,19 @@ static int a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, static int a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){ char uidbuf[sizeof "18446744073709551615"], - wbuf[(((sizeof("18446744073709551615") -1) * 2) | - (sizeof("cd ..;rm -rf ") + sizeof("18446744073709551615")) | - (sizeof("XDG_RUNTIME_DIR=") + sizeof(a_RUNTIME_DIR_OUTER) + + wbuf[((sizeof("XDG_RUNTIME_DIR=") + sizeof(a_RUNTIME_DIR_OUTER) + sizeof(a_RUNTIME_DIR_BASE) + sizeof("18446744073709551615")) | (sizeof("XDG_CONFIG_DIRS=") + PATH_MAX) ) +1]; - struct flock flp; struct stat st; - uint64_t sessions; struct passwd *pwp; char const *emsg; - int cntrlfd, fd, cwdfd, only_runtime, notroot, res, uidbuflen; + int cwdfd, only_runtime, notroot, res, uidbuflen; char const *user; (void)flags; user = "<unset>"; - cntrlfd = fd = cwdfd = -1; + cwdfd = -1; only_runtime = notroot = 0; /* Command line */ @@ -114,7 +101,8 @@ a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){ goto jerr; } } - } + }else + goto jok; /* No longer used, session counting does not work */ /* We need the user we go for */ if((res = pam_get_item(pamh, PAM_USER, (void const**)&user) @@ -143,7 +131,7 @@ a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){ } /* We try create the base directory once as necessary */ - if(isopen){ + /*if(isopen)*/{ res = 0; while(fstatat(cwdfd, a_RUNTIME_DIR_BASE, &st, AT_SYMLINK_NOFOLLOW ) == -1){ @@ -153,7 +141,7 @@ a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){ goto jerr; } - if(mkdirat(cwdfd, a_RUNTIME_DIR_BASE, 0711) == -1){ + if(mkdirat(cwdfd, a_RUNTIME_DIR_BASE, a_RUNTIME_DIR_BASE_MODE) == -1){ emsg = "cannot create base directory " a_RUNTIME_DIR_OUTER "/" a_RUNTIME_DIR_BASE; goto jerr; @@ -170,148 +158,47 @@ a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){ close(cwdfd); cwdfd = res; - /* Landed in the runtime base dir, obtain our lock */ - if((cntrlfd = openat(cwdfd, a_LOCK_FILE, - (O_CREAT | O_WRONLY | O_NOFOLLOW | O_NOCTTY), - (S_IRUSR | S_IWUSR))) == -1){ - emsg = "cannot open control lock file"; - goto jerr; - } - - for(res = a_LOCK_TRIES;;){ - memset(&flp, 0, sizeof flp); - flp.l_type = F_WRLCK; - flp.l_start = 0; - flp.l_whence = SEEK_SET; - flp.l_len = 0; - - if(fcntl(cntrlfd, F_SETLKW, &flp) != -1) - break; - - if(errno != EINTR){ - emsg = "unexpected error obtaining lock on control lock file"; - goto jerr; - } - if(--res == 0){ - emsg = "cannot obtain lock on control lock file"; - goto jerr; - } - } - /* Turn to user management */ uidbuflen = snprintf(uidbuf, sizeof(uidbuf), "%lu", (unsigned long)pwp->pw_uid); /* We create the per-user directory on isopen time as necessary */ - for(res = 0;; ++res){ - int nfd; - - if((nfd = openat(cwdfd, uidbuf, (O_PATH | O_DIRECTORY | O_NOFOLLOW)) - ) != -1){ - close(cwdfd); - cwdfd = nfd; - break; - }else{ - if(errno == ENOENT){ - if(!isopen) - goto jok; - if(res != 0) - goto jeurd; + /*if(isopen)*/{ + for(res = 0;; ++res){ + int nfd; + + if((nfd = openat(cwdfd, uidbuf, (O_PATH | O_DIRECTORY | O_NOFOLLOW)) + ) != -1){ + close(cwdfd); + cwdfd = nfd; + break; }else{ + if(errno == ENOENT){ + if(!isopen) + goto jok; + if(res != 0) + goto jeurd; + }else{ jeurd: - emsg = "per user XDG_RUNTIME_DIR not accessible"; - goto jerr; + emsg = "per user XDG_RUNTIME_DIR not accessible"; + goto jerr; + } } - } - - if(mkdirat(cwdfd, uidbuf, 0700) == -1){ - emsg = "cannot create per user XDG_RUNTIME_DIR"; - goto jerr; - } - if(fchownat(cwdfd, uidbuf, pwp->pw_uid, pwp->pw_gid, AT_SYMLINK_NOFOLLOW - ) == -1){ - emsg = "cannot chown(2) per user XDG_RUNTIME_DIR"; - goto jerr; - } - } - - /* Read session counter; be simple and assume 0 if non-existent, this should - * not happen in practice */ - sessions = 0; - if((fd = openat(cwdfd, a_DAT_FILE, O_RDONLY)) != -1){ - char *ep; - ssize_t r; - while((r = read(fd, wbuf, sizeof(wbuf) -1)) == -1){ - if(errno != EINTR){ - emsg = "I/O error while reading session counter"; + if(mkdirat(cwdfd, uidbuf, 0700) == -1){ + emsg = "cannot create per user XDG_RUNTIME_DIR"; + goto jerr; + } + if(fchownat(cwdfd, uidbuf, pwp->pw_uid, pwp->pw_gid, + AT_SYMLINK_NOFOLLOW) == -1){ + emsg = "cannot chown(2) per user XDG_RUNTIME_DIR"; goto jerr; } } - - /* We have written this as a valid POSIX text file, then, so chop tail */ - if(r < 1 || (size_t)r >= (sizeof(wbuf) -1) / 2){ -jecnt: - emsg = "session counter corrupted, ask administrator to remove " - a_RUNTIME_DIR_OUTER "/" a_RUNTIME_DIR_BASE "/YOUR-UID/" - a_DAT_FILE; - goto jerr; - } - for(;;){ - char c; - - c = wbuf[(size_t)r - 1]; - if(c == '\0' || c == '\n'){ - if(--r == 0) - goto jecnt; - }else - break; - } - wbuf[(size_t)r] = '\0'; - - sessions = strtoull(wbuf, &ep, 10); - if(sessions == ULLONG_MAX || ep == wbuf || *ep != '\0') - goto jecnt; - - close(fd); - fd = -1; - } - - if(isopen) - ++sessions; - /* == 0 should never happen, but just handled it easily */ - else if(sessions == 0 || --sessions == 0){ - /* This is ridiculously simple, but everything else would be opposite */ - char const cmd[] = "rm -rf " a_RUNTIME_DIR_OUTER "/" - a_RUNTIME_DIR_BASE "/"; - - memcpy(wbuf, cmd, sizeof(cmd) -1); - memcpy(&wbuf[sizeof(cmd) -1], uidbuf, uidbuflen +1); - res = system(wbuf); - if(!WIFEXITED(res) || WEXITSTATUS(res) != 0){ - emsg = "unable to rm(1) -rf per user XDG_RUNTIME_DIR"; - errno = EINVAL; - goto jerr; - } - goto jok; } - /* Write out session counter (as a valid POSIX text file) */ - res = snprintf(wbuf, sizeof wbuf, "%llu\n", (unsigned long long)sessions); - - if(((fd = openat(cwdfd, a_DAT_FILE, - (O_CREAT | O_TRUNC | O_WRONLY | O_SYNC | O_NOFOLLOW | O_NOCTTY), - (S_IRUSR | S_IWUSR))) == -1) || write(fd, wbuf, res) != res){ - emsg = "cannot write session counter, ask administrator to remove " - a_RUNTIME_DIR_OUTER "/" a_RUNTIME_DIR_BASE "/YOUR-UID/" - a_DAT_FILE; - goto jerr; - } - close(fd); - fd = -1; - /* When opening, we want to put environment variables, too */ - if(isopen){ + /*if(isopen)*/{ char *cp; /* XDG_RUNTIME_DIR */ @@ -374,10 +261,6 @@ jecnt: jok: res = PAM_SUCCESS; jleave: - if(fd != -1) - close(fd); - if(cntrlfd != -1) - close(cntrlfd); if(cwdfd != -1) close(cwdfd);
participants (1)
-
crux@crux.nu