forked from ports/contrib
pam_xdg: update to v0.8.0
This commit is contained in:
parent
6a74437922
commit
0c7b9fd7f7
@ -1,7 +1,5 @@
|
|||||||
untrusted comment: verify with /etc/ports/contrib.pub
|
untrusted comment: verify with /etc/ports/contrib.pub
|
||||||
RWSagIOpLGJF35ByKJGqZDYTDYgapw8YNFcmoQfuIz4G84szVxTjO1rS11BBqoORBYTNjhd+T3T+UY/nvIWL0h6PK6YhrCZ7rwA=
|
RWSagIOpLGJF38vXUmHccJtpWh6lLPLXjBsQAIu9jyBjAwuy+q2IRksNUSDkG3WYjwshJpy6iLYkM4T9wwCbIkPCYR7Un9U7jA8=
|
||||||
SHA256 (Pkgfile) = c8ca4da1cb69de37a134d64ca3acbe68d49a5ca2f07c03f86919d9287acd39bb
|
SHA256 (Pkgfile) = 40650e03f6f56f26595ee0225fae4c3b77bb4721531c909e69a15b4b65246b29
|
||||||
SHA256 (.footprint) = 56d789b652e6167f5fb93e1e6d48243e13f598c6d9a72705a8e54a003574ba31
|
SHA256 (.footprint) = 56d789b652e6167f5fb93e1e6d48243e13f598c6d9a72705a8e54a003574ba31
|
||||||
SHA256 (pam_xdg.c) = 3ed98ccd23cee452086722be11c605420b5b96d2a5bb6734270121f1eb18463c
|
SHA256 (pam_xdg-0.8.0.tar.gz) = 386ce8311d77e4a60792b1085c72f34484f44a93d1db1de7bed1d4fb423f8f48
|
||||||
SHA256 (pam_xdg.8) = 946a65f7559e5e9c343fecf565fc3ddee8227e29e2dbb1729eaa96ee6eff75f1
|
|
||||||
SHA256 (makefile) = 2466f499c3e84fd821176371fa9ff78143bf94b9ec09fd9e654b35613e4ead7d
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
# Description: PAM module to manage XDG Base Directories (sessions)
|
# Description: PAM module to manage XDG Base Directories (see manual)
|
||||||
# URL: https://www.sdaoden.eu/code.html#s-toolbox
|
# URL: https://www.sdaoden.eu/code.html#s-toolbox
|
||||||
# Maintainer: Steffen Nurpmeso, steffen at sdaoden dot eu
|
# Maintainer: Steffen Nurpmeso, steffen at sdaoden dot eu
|
||||||
|
|
||||||
name=pam_xdg
|
name=pam_xdg
|
||||||
version=20210801
|
version=0.8.0
|
||||||
release=1
|
release=1
|
||||||
source=($name.c $name.8 makefile)
|
source=(https://ftp.sdaoden.eu/${name}-${version}.tar.gz)
|
||||||
|
|
||||||
build () {
|
build () {
|
||||||
|
cd ${name}-${version}
|
||||||
make install DESTDIR=$PKG
|
make install DESTDIR=$PKG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
README for pam_xdg
|
|
||||||
|
|
||||||
PAM module that handles the XDG Base Directory Specification[1]
|
|
||||||
directories, including creation of XDG_RUNTIME_DIR and injection
|
|
||||||
of according environment variables into user sessions.
|
|
||||||
|
|
||||||
For it to work it must be included in /etc/pam.d -- to make it a
|
|
||||||
vivid part of session handling the file /etc/pam.d/common-session
|
|
||||||
seems best. Include the following early:
|
|
||||||
|
|
||||||
session optional pam_xdg.so [notroot] [runtime] [track_sessions]
|
|
||||||
|
|
||||||
Use notroot argument to only handle XDG for non-root users.
|
|
||||||
Use runtime argument to only handle of XDG_RUNTIME_DIR.
|
|
||||||
Use track_sessions to remove XDG_RUNTIME_DIR once the last user
|
|
||||||
session ends (take care of CAVEATS of manual, maybe).
|
|
||||||
|
|
||||||
[1] https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
|
@ -1,41 +0,0 @@
|
|||||||
#@ Makefile for pam_xdg(8).
|
|
||||||
|
|
||||||
PREFIX = /
|
|
||||||
MANPREFIX = /usr
|
|
||||||
DESTDIR =
|
|
||||||
LIBDIR = $(DESTDIR)$(PREFIX)/lib/security
|
|
||||||
MANDIR = $(DESTDIR)$(MANPREFIX)/share/man/man8
|
|
||||||
NAME = pam_xdg
|
|
||||||
|
|
||||||
CC = cc
|
|
||||||
CFLAGS = -DNDEBUG \
|
|
||||||
-O2 -W -Wall -Wextra -pedantic \
|
|
||||||
-Wno-uninitialized -Wno-unused-result -Wno-unused-value \
|
|
||||||
-fno-asynchronous-unwind-tables -fno-unwind-tables \
|
|
||||||
-fno-common \
|
|
||||||
-fstrict-aliasing -fstrict-overflow \
|
|
||||||
-fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIE
|
|
||||||
LDFLAGS = -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,--as-needed \
|
|
||||||
-Wl,--enable-new-dtags -pie -shared
|
|
||||||
INSTALL = install
|
|
||||||
RM = rm
|
|
||||||
|
|
||||||
.PHONY: all clean distclean install uninstall
|
|
||||||
all: $(NAME).so
|
|
||||||
|
|
||||||
$(NAME).so: $(NAME).c
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $(@) $(?)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) -f $(NAME).so
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
|
|
||||||
install: all
|
|
||||||
$(INSTALL) -D -m 0755 $(NAME).so $(LIBDIR)/$(NAME).so
|
|
||||||
$(INSTALL) -D -m 0644 $(NAME).8 $(MANDIR)/$(NAME).8
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
$(RM) -f $(LIBDIR)/$(NAME).so $(MANDIR)/$(NAME).8
|
|
||||||
|
|
||||||
# s-mk-mode
|
|
@ -1,112 +0,0 @@
|
|||||||
.\"@ pam_xdg - manage XDG Base Directories (runtime dir life time, environ).
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2021 Steffen Nurpmeso <steffen@sdaoden.eu>.
|
|
||||||
.\" SPDX-License-Identifier: ISC
|
|
||||||
.\"
|
|
||||||
.\" Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
.\" purpose with or without fee is hereby granted, provided that the above
|
|
||||||
.\" copyright notice and this permission notice appear in all copies.
|
|
||||||
.\"
|
|
||||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
.
|
|
||||||
.Dd August 1, 2021
|
|
||||||
.Dt PAM_XDG 8
|
|
||||||
.Os
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pam_xdg.so
|
|
||||||
.Nd PAM module that manages XDG Base Directories
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.
|
|
||||||
.Nm
|
|
||||||
.Op Ar runtime
|
|
||||||
.Op Ar notroot
|
|
||||||
.Op Ar track_sessions Op Ar per_user_lock
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.
|
|
||||||
.Nm
|
|
||||||
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
|
|
||||||
.Lk https://specifications.\:freedesktop.\:org/basedir-\:\
|
|
||||||
spec/\:basedir-\:spec-\:latest.html "XDG Base Directory Specification"
|
|
||||||
into user sessions.
|
|
||||||
.
|
|
||||||
.Pp
|
|
||||||
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 runtime
|
|
||||||
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 and
|
|
||||||
perform no actions for root.
|
|
||||||
Lastly
|
|
||||||
.Ar track_sessions
|
|
||||||
will enable session tracking: once the last session ends, the user's
|
|
||||||
.Ev XDG_RUNTIME_DIR
|
|
||||||
will be recursively removed; on high-load servers then setting
|
|
||||||
.Ar per_user_lock
|
|
||||||
will reduce lock file lock contention.
|
|
||||||
.
|
|
||||||
.Pp
|
|
||||||
In order to make use of this module, place the following in the
|
|
||||||
.Ql session
|
|
||||||
part of the control file of desire under
|
|
||||||
.Pa /etc/pam.d ,
|
|
||||||
on Linux it may be
|
|
||||||
.Pa /etc/pam.d/common-session
|
|
||||||
if that exists, on BSD's the files
|
|
||||||
.Pa /etc/pam.d/system
|
|
||||||
as well as
|
|
||||||
.Pa /etc/pam.d/login ,
|
|
||||||
.Pa /etc/pam.d/sshd
|
|
||||||
and
|
|
||||||
.Pa /etc/pam.d/su
|
|
||||||
may be desirable, adjusting paths as necessary:
|
|
||||||
.
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
session optional pam_xdg.so notroot track_sessions
|
|
||||||
.Ed
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh "SEE ALSO"
|
|
||||||
.
|
|
||||||
.Xr pam 3 ,
|
|
||||||
.Xr pam.conf 5
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh AUTHORS
|
|
||||||
.
|
|
||||||
.An "Steffen Nurpmeso" Aq steffen@sdaoden.eu .
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.Sh CAVEATS
|
|
||||||
.
|
|
||||||
On Unix systems any
|
|
||||||
.Dq daemonized
|
|
||||||
program or script is reparented to the program running with PID 1,
|
|
||||||
most likely leaving the PAM user session without PAM recognizing this.
|
|
||||||
Yet careless such code may hold or expect availability of resources of
|
|
||||||
the session it just left, truly performing cleanup when sessions end
|
|
||||||
seems thus unwise.
|
|
||||||
Since so many PAM modules do support session tracking and cleanup
|
|
||||||
.Nm
|
|
||||||
readded optional support for this.
|
|
||||||
.
|
|
||||||
.\" s-ts-mode
|
|
@ -1,521 +0,0 @@
|
|||||||
/*@ pam_xdg - manage XDG Base Directories (runtime dir life time, environment).
|
|
||||||
*@ See pam_xdg.8 for more.
|
|
||||||
*@ - According to XDG Base Directory Specification, v0.7.
|
|
||||||
*@ - Supports libpam (Linux) and OpenPAM.
|
|
||||||
*@ - Requires C preprocessor with __VA_ARGS__ support!
|
|
||||||
*@ - Uses "rm -rf" to drop per-user directories. XXX Unroll this? nftw?
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021 Steffen Nurpmeso <steffen@sdaoden.eu>.
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* For these a leading \1 is replaced with struct passwd::pw_dir.
|
|
||||||
* Be aware we use a stack buffer for storage */
|
|
||||||
#define a_XDG_DATA_HOME_DEF "\1/.local/share"
|
|
||||||
#define a_XDG_CONFIG_HOME_DEF "\1/.config"
|
|
||||||
#define a_XDG_DATA_DIRS_DEF "/usr/local/share:/usr/share"
|
|
||||||
#define a_XDG_CONFIG_DIRS_DEF "/etc/xdg/"
|
|
||||||
#define a_XDG_CACHE_HOME_DEF "\1/.cache"
|
|
||||||
|
|
||||||
/* We create the outer directories as necessary (stack buffer storage!) */
|
|
||||||
#define a_RUNTIME_DIR_OUTER "/run"
|
|
||||||
#define a_RUNTIME_DIR_OUTER_MODE 0755
|
|
||||||
#define a_RUNTIME_DIR_BASE "user"
|
|
||||||
#define a_RUNTIME_DIR_BASE_MODE 0755 /* 0711? */
|
|
||||||
|
|
||||||
/* Note: we manage these relative to the per-user directory!
|
|
||||||
* a_LOCK_FILE is only used without "per_user_lock" */
|
|
||||||
#define a_LOCK_FILE "../." a_XDG ".lck"
|
|
||||||
#define a_LOCK_TRIES 10
|
|
||||||
|
|
||||||
#define a_DAT_FILE "." a_XDG ".dat"
|
|
||||||
|
|
||||||
/* >8 -- 8< */
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
#define _ATFILE_SOURCE
|
|
||||||
*/
|
|
||||||
#define _GNU_SOURCE /* Always the same mess */
|
|
||||||
|
|
||||||
#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> /* xxx not, actually!?! */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <security/pam_appl.h>
|
|
||||||
#include <security/pam_modules.h>
|
|
||||||
#ifdef OPENPAM_VERSION
|
|
||||||
# include <security/openpam.h>
|
|
||||||
#else
|
|
||||||
# include <security/pam_ext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef OPENPAM_VERSION
|
|
||||||
#else
|
|
||||||
# include <syslog.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Who are we? */
|
|
||||||
#define a_XDG "pam_xdg"
|
|
||||||
|
|
||||||
/* _XOPEN_PATH_MAX POSIX 2008/Cor 1-2013 */
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
# define PATH_MAX 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* */
|
|
||||||
#ifdef O_SEARCH
|
|
||||||
# define a_O_SEARCH O_SEARCH
|
|
||||||
#elif defined O_PATH
|
|
||||||
# define a_O_SEARCH O_PATH
|
|
||||||
#else
|
|
||||||
/* Well, hardly, but not in practice so do not #error out */
|
|
||||||
# define a_O_SEARCH 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* libpam / OpenPAM compat */
|
|
||||||
#ifdef OPENPAM_VERSION
|
|
||||||
# define a_LOG(HDL, LVL, ...) ((void)HDL, openpam_log(LVL, __VA_ARGS__))
|
|
||||||
# define a_LOG_ERR PAM_LOG_ERROR
|
|
||||||
# define a_LOG_NOTICE PAM_LOG_NOTICE
|
|
||||||
#else
|
|
||||||
# define a_LOG(HDL, LVL, ...) pam_syslog(HDL, LVL, __VA_ARGS__)
|
|
||||||
# define a_LOG_ERR LOG_ERR
|
|
||||||
# define a_LOG_NOTICE LOG_NOTICE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Just put it all in one big fun, use two exec paths */
|
|
||||||
static int a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc,
|
|
||||||
const char **argv);
|
|
||||||
|
|
||||||
static int
|
|
||||||
a_xdg(int isopen, pam_handle_t *pamh, int flags, int argc, const char **argv){
|
|
||||||
enum a_flags{
|
|
||||||
a_NONE,
|
|
||||||
/* Options */
|
|
||||||
a_RUNTIME = 1u<<0,
|
|
||||||
a_NOTROOT = 1u<<1,
|
|
||||||
a_SESSIONS = 1u<<16,
|
|
||||||
a_USER_LOCK = 1u<<17,
|
|
||||||
|
|
||||||
/* Flags */
|
|
||||||
a_MPV = 1u<<29, /* Multi-Purpose-Vehicle */
|
|
||||||
a_SKIP_XDG = 1u<<30 /* We shall not act */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct a_dirtree{
|
|
||||||
char const *name;
|
|
||||||
int mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct a_dirtree const a_dirtree[] = {
|
|
||||||
{a_RUNTIME_DIR_OUTER, a_RUNTIME_DIR_OUTER_MODE},
|
|
||||||
{a_RUNTIME_DIR_BASE, a_RUNTIME_DIR_BASE_MODE},
|
|
||||||
{NULL, 0} /* XXX -> nelem/item/countof */
|
|
||||||
};
|
|
||||||
static int f_saved;
|
|
||||||
|
|
||||||
char uidbuf[sizeof "../.18446744073709551615"],
|
|
||||||
xbuf[((sizeof("XDG_RUNTIME_DIR=") + sizeof(a_RUNTIME_DIR_OUTER) +
|
|
||||||
sizeof(a_RUNTIME_DIR_BASE) +
|
|
||||||
sizeof("../.18446744073709551615")) |
|
|
||||||
(sizeof("XDG_CONFIG_DIRS=") + PATH_MAX)
|
|
||||||
) +1];
|
|
||||||
struct a_dirtree dt_user;
|
|
||||||
struct a_dirtree const *dtp;
|
|
||||||
struct passwd *pwp;
|
|
||||||
char const *emsg;
|
|
||||||
int cwdfd, cntrlfd, datfd, f, res, uidbuflen;
|
|
||||||
char const *user;
|
|
||||||
|
|
||||||
user = "<unset>";
|
|
||||||
cwdfd = AT_FDCWD;
|
|
||||||
datfd = cntrlfd = -1;
|
|
||||||
|
|
||||||
/* Command line */
|
|
||||||
if(isopen){
|
|
||||||
f = a_NONE;
|
|
||||||
|
|
||||||
for(; argc > 0; ++argv, --argc){
|
|
||||||
if(!strcmp(argv[0], "runtime"))
|
|
||||||
f |= a_RUNTIME;
|
|
||||||
else if(!strcmp(argv[0], "rundir")){ /* XXX COMPAT */
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE,
|
|
||||||
a_XDG ": \"rundir\" was a misdocumentation of \"runtime\", "
|
|
||||||
"sorry for this");
|
|
||||||
f |= a_RUNTIME;
|
|
||||||
}
|
|
||||||
else if(!strcmp(argv[0], "notroot"))
|
|
||||||
f |= a_NOTROOT;
|
|
||||||
else if(!strcmp(argv[0], "track_sessions"))
|
|
||||||
f |= a_SESSIONS;
|
|
||||||
else if(!strcmp(argv[0], "per_user_lock"))
|
|
||||||
f |= a_USER_LOCK;
|
|
||||||
else if(!(flags & PAM_SILENT)){
|
|
||||||
emsg = "command line";
|
|
||||||
errno = EINVAL;
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((f & a_USER_LOCK) && !(f & a_SESSIONS))
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE,
|
|
||||||
a_XDG ": \"per_user_lock\" requires \"track_sessions\"");
|
|
||||||
}else{
|
|
||||||
f = f_saved;
|
|
||||||
|
|
||||||
if(f & a_SKIP_XDG)
|
|
||||||
goto jok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need the user we go for */
|
|
||||||
if((res = pam_get_item(pamh, PAM_USER, (void const**)&user)
|
|
||||||
) != PAM_SUCCESS){
|
|
||||||
user = "<lookup failed>";
|
|
||||||
emsg = "cannot query PAM_USER name";
|
|
||||||
goto jepam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No PAM failure, no PAM_USER_UNKNOWN here: we are no authentificator! */
|
|
||||||
if((pwp = getpwnam(user)) == NULL){
|
|
||||||
emsg = "host does not know about user";
|
|
||||||
errno = EINVAL;
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((f & a_NOTROOT) && pwp->pw_uid == 0){
|
|
||||||
f |= a_SKIP_XDG;
|
|
||||||
goto jok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our lockfile and per-user directory name */
|
|
||||||
uidbuflen = snprintf(uidbuf, sizeof(uidbuf), "../.%lu", /* xxx error?? */
|
|
||||||
(unsigned long)pwp->pw_uid) - 3;
|
|
||||||
|
|
||||||
dt_user.name = &uidbuf[4];
|
|
||||||
dt_user.mode = 0700; /* XDG implied */
|
|
||||||
|
|
||||||
/* Handle tree, go to user runtime. On *BSD outermost may not exist! */
|
|
||||||
for(/*f &= ~a_MPV,*/ dtp = a_dirtree;;){
|
|
||||||
int e;
|
|
||||||
gid_t oegid;
|
|
||||||
mode_t oumask;
|
|
||||||
|
|
||||||
if((res = openat(cwdfd, dtp->name,
|
|
||||||
(a_O_SEARCH | O_DIRECTORY | O_NOFOLLOW))) != -1){
|
|
||||||
if(cwdfd != AT_FDCWD)
|
|
||||||
close(cwdfd); /* XXX error hdl */
|
|
||||||
cwdfd = res;
|
|
||||||
|
|
||||||
if(dtp == &dt_user)
|
|
||||||
break;
|
|
||||||
else if((++dtp)->name == NULL)
|
|
||||||
dtp = &dt_user;
|
|
||||||
f &= ~a_MPV;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isopen)
|
|
||||||
/* XXX Entire directory tree disappeared while sessions were open!
|
|
||||||
* XXX Silently out!?! */
|
|
||||||
goto jok;
|
|
||||||
|
|
||||||
/* We try creating the directories once as necessary */
|
|
||||||
if((f & a_MPV) || errno != ENOENT){
|
|
||||||
emsg = "cannot obtain chdir(2) descriptor (within) tree "
|
|
||||||
a_RUNTIME_DIR_OUTER "/" a_RUNTIME_DIR_BASE;
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
f |= a_MPV;
|
|
||||||
|
|
||||||
oumask = umask(0000);
|
|
||||||
oegid = getegid();
|
|
||||||
setegid(0);
|
|
||||||
res = mkdirat(cwdfd, dtp->name, dtp->mode);
|
|
||||||
e = (res == -1) ? errno : 0;
|
|
||||||
setegid(oegid);
|
|
||||||
umask(oumask);
|
|
||||||
|
|
||||||
if(res == -1){
|
|
||||||
if(e != EEXIST){
|
|
||||||
emsg = "cannot create directory (within) tree "
|
|
||||||
a_RUNTIME_DIR_OUTER "/" a_RUNTIME_DIR_BASE;
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
}else if(cwdfd == AT_FDCWD)
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE,
|
|
||||||
a_XDG ": " a_RUNTIME_DIR_OUTER " did not exist, but should be "
|
|
||||||
"(a mount point of) volatile storage!");
|
|
||||||
/* Just chown it! */
|
|
||||||
else if(dtp == &dt_user &&
|
|
||||||
fchownat(cwdfd, &uidbuf[4], pwp->pw_uid, pwp->pw_gid,
|
|
||||||
AT_SYMLINK_NOFOLLOW) == -1){
|
|
||||||
emsg = "cannot chown(2) per user XDG_RUNTIME_DIR";
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In session mode we have to manage the counter file */
|
|
||||||
if(f & a_SESSIONS){
|
|
||||||
unsigned long long int sessions;
|
|
||||||
|
|
||||||
/* Landed in the runtime base dir, obtain our lock */
|
|
||||||
if((cntrlfd = openat(cwdfd,
|
|
||||||
(f & a_USER_LOCK ? uidbuf : 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;;){
|
|
||||||
struct flock flp;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* XXX It may happen we cannot manage the lock and thus not access
|
|
||||||
* XXX the session counter, ie this session is zombie to us.
|
|
||||||
* XXX Just like counter below, should globally disable sessions!! */
|
|
||||||
if(errno != EINTR){
|
|
||||||
emsg = "unexpected error obtaining lock on lock control file";
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
if(--res == 0){
|
|
||||||
emsg = "cannot obtain lock on lock control file";
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sessions = 0;
|
|
||||||
|
|
||||||
if((datfd = openat(cwdfd, a_DAT_FILE, O_RDONLY)) != -1){
|
|
||||||
char *ep;
|
|
||||||
ssize_t r;
|
|
||||||
|
|
||||||
while((r = read(datfd, xbuf, sizeof(xbuf) -1)) == -1){
|
|
||||||
if(errno != EINTR)
|
|
||||||
goto jecnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(datfd);
|
|
||||||
datfd = -1;
|
|
||||||
|
|
||||||
xbuf[(size_t)r] = '\0';
|
|
||||||
sessions = strtoull(xbuf, &ep, 10);
|
|
||||||
/* Do not log too often for "session counter error"s, as below */
|
|
||||||
if(ep == xbuf){
|
|
||||||
res = PAM_SESSION_ERR;
|
|
||||||
goto jleave;
|
|
||||||
}else if(sessions == ULLONG_MAX || ep != &xbuf[(size_t)r])
|
|
||||||
goto jecnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isopen)
|
|
||||||
++sessions;
|
|
||||||
else if(sessions > 0)
|
|
||||||
--sessions;
|
|
||||||
|
|
||||||
if(!isopen && sessions == 0){ /* former.. hmmm. */
|
|
||||||
/* Ridiculously simple, but everything else would be the opposite.
|
|
||||||
* Ie, E[MN]FILE failures, or whatever else */
|
|
||||||
char const cmd[] = "rm -rf " a_RUNTIME_DIR_OUTER "/"
|
|
||||||
a_RUNTIME_DIR_BASE "/";
|
|
||||||
|
|
||||||
memcpy(xbuf, cmd, sizeof(cmd) -1);
|
|
||||||
memcpy(&xbuf[sizeof(cmd) -1], &uidbuf[4], uidbuflen +1);
|
|
||||||
|
|
||||||
res = system(xbuf);
|
|
||||||
if(!WIFEXITED(res) || WEXITSTATUS(res) != 0){
|
|
||||||
emsg = "unable to rm(1) -rf per user XDG_RUNTIME_DIR";
|
|
||||||
errno = EINVAL;
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
/* This is the end .. */
|
|
||||||
goto jok;
|
|
||||||
}else{
|
|
||||||
/* Write out session counter */
|
|
||||||
res = snprintf(xbuf, sizeof xbuf, "%llu", sessions); /* xxx error? */
|
|
||||||
|
|
||||||
if(((datfd = openat(cwdfd, a_DAT_FILE,
|
|
||||||
(O_CREAT | O_TRUNC | O_WRONLY | O_SYNC | O_NOFOLLOW |
|
|
||||||
O_NOCTTY),
|
|
||||||
(S_IRUSR | S_IWUSR))) == -1) ||
|
|
||||||
write(datfd, xbuf, res) != res){
|
|
||||||
jecnt:
|
|
||||||
/* Ensure read above fails, so that henceforth session teardown is
|
|
||||||
* skipped for this user */
|
|
||||||
truncate(a_DAT_FILE, 0);
|
|
||||||
emsg = "counter file error, disabled session tracking for user";
|
|
||||||
goto jerr;
|
|
||||||
}
|
|
||||||
close(datfd);
|
|
||||||
datfd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When opening, we want to put environment variables, too */
|
|
||||||
if(isopen){
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
/* XDG_RUNTIME_DIR */
|
|
||||||
cp = xbuf;
|
|
||||||
memcpy(cp, "XDG_RUNTIME_DIR=", sizeof("XDG_RUNTIME_DIR=") -1);
|
|
||||||
cp += sizeof("XDG_RUNTIME_DIR=") -1;
|
|
||||||
memcpy(cp, a_RUNTIME_DIR_OUTER, sizeof(a_RUNTIME_DIR_OUTER) -1);
|
|
||||||
cp += sizeof(a_RUNTIME_DIR_OUTER) -1;
|
|
||||||
*cp++ = '/';
|
|
||||||
memcpy(cp, a_RUNTIME_DIR_BASE, sizeof(a_RUNTIME_DIR_BASE) -1);
|
|
||||||
cp += sizeof(a_RUNTIME_DIR_BASE) -1;
|
|
||||||
*cp++ = '/';
|
|
||||||
memcpy(cp, &uidbuf[4], uidbuflen);
|
|
||||||
|
|
||||||
if((res = pam_putenv(pamh, xbuf)) != PAM_SUCCESS)
|
|
||||||
goto jepam;
|
|
||||||
|
|
||||||
/* And the rest unless disallowed */
|
|
||||||
if(!(f & a_RUNTIME)){
|
|
||||||
struct a_dir{
|
|
||||||
char const *name;
|
|
||||||
size_t len;
|
|
||||||
char const *defval;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct a_dir const a_dirs[] = {
|
|
||||||
{"XDG_DATA_HOME=", sizeof("XDG_DATA_HOME=") -1,
|
|
||||||
a_XDG_DATA_HOME_DEF},
|
|
||||||
{"XDG_CONFIG_HOME=", sizeof("XDG_CONFIG_HOME=") -1,
|
|
||||||
a_XDG_CONFIG_HOME_DEF},
|
|
||||||
{"XDG_DATA_DIRS=", sizeof("XDG_DATA_DIRS=") -1,
|
|
||||||
a_XDG_DATA_DIRS_DEF},
|
|
||||||
{"XDG_CONFIG_DIRS=", sizeof("XDG_CONFIG_DIRS=") -1,
|
|
||||||
a_XDG_CONFIG_DIRS_DEF},
|
|
||||||
{"XDG_CACHE_HOME=", sizeof("XDG_CACHE_HOME=") -1,
|
|
||||||
a_XDG_CACHE_HOME_DEF},
|
|
||||||
{NULL,0,NULL} /* XXX -> nelem/item/countof */
|
|
||||||
};
|
|
||||||
|
|
||||||
char const *src;
|
|
||||||
struct a_dir const *adp;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
i = strlen(pwp->pw_dir);
|
|
||||||
|
|
||||||
for(adp = a_dirs; adp->name != NULL; ++adp){
|
|
||||||
cp = xbuf;
|
|
||||||
memcpy(cp, adp->name, adp->len);
|
|
||||||
cp += adp->len;
|
|
||||||
if(*(src = adp->defval) == '\1'){
|
|
||||||
memcpy(cp, pwp->pw_dir, i);
|
|
||||||
cp += i;
|
|
||||||
++src;
|
|
||||||
}
|
|
||||||
memcpy(cp, src, strlen(src) +1);
|
|
||||||
|
|
||||||
if((res = pam_putenv(pamh, xbuf)) != PAM_SUCCESS)
|
|
||||||
goto jepam;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jok:
|
|
||||||
res = PAM_SUCCESS;
|
|
||||||
jleave:
|
|
||||||
if(datfd != -1)
|
|
||||||
close(datfd);
|
|
||||||
if(cntrlfd != -1)
|
|
||||||
close(cntrlfd);
|
|
||||||
if(cwdfd != -1 && cwdfd != AT_FDCWD) /* >=0, but AT_FDCWD unspecified */
|
|
||||||
close(cwdfd);
|
|
||||||
|
|
||||||
f_saved = f;
|
|
||||||
return (res == PAM_SUCCESS) ? PAM_SUCCESS : PAM_SESSION_ERR;
|
|
||||||
|
|
||||||
jerr:
|
|
||||||
a_LOG(pamh, a_LOG_ERR, a_XDG ": user %s: %s: %s\n",
|
|
||||||
user, emsg, strerror(errno));
|
|
||||||
f |= a_SKIP_XDG;
|
|
||||||
res = PAM_SESSION_ERR;
|
|
||||||
goto jleave;
|
|
||||||
|
|
||||||
jepam:
|
|
||||||
a_LOG(pamh, a_LOG_ERR, a_XDG ": user %s: PAM failure: %s\n",
|
|
||||||
user, pam_strerror(pamh, res));
|
|
||||||
f |= a_SKIP_XDG;
|
|
||||||
goto jleave;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pam_sm_open_session(pam_handle_t *pamh, int flags,
|
|
||||||
int argc, const char **argv){
|
|
||||||
return a_xdg(1, pamh, flags, argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pam_sm_close_session(pam_handle_t *pamh, int flags,
|
|
||||||
int argc, const char **argv){
|
|
||||||
return a_xdg(0, pamh, flags, argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv){
|
|
||||||
(void)flags;
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE, a_XDG ": pam_sm_acct_mgmt not used");
|
|
||||||
|
|
||||||
return PAM_SERVICE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv){
|
|
||||||
(void)flags;
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE, a_XDG ": pam_sm_setcred not used");
|
|
||||||
|
|
||||||
return PAM_SERVICE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv){
|
|
||||||
(void)flags;
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
a_LOG(pamh, a_LOG_NOTICE, a_XDG ": pam_sm_chauthtok not used");
|
|
||||||
|
|
||||||
return PAM_SERVICE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* s-it-mode */
|
|
Loading…
x
Reference in New Issue
Block a user