Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8a41d9480 |
@@ -1,34 +0,0 @@
|
|||||||
image: alpine/latest
|
|
||||||
# apk add --update alpine-sdk
|
|
||||||
packages:
|
|
||||||
- cmd:setcap
|
|
||||||
- autoconf
|
|
||||||
- automake
|
|
||||||
- byacc
|
|
||||||
- expect
|
|
||||||
- gettext
|
|
||||||
- gettext-dev
|
|
||||||
- gettext-lang
|
|
||||||
- libbsd-dev
|
|
||||||
- libcap-dev
|
|
||||||
- libtool
|
|
||||||
- linux-pam-dev
|
|
||||||
- pkgconf
|
|
||||||
- sed
|
|
||||||
sources:
|
|
||||||
- https://github.com/shadow-maint/shadow
|
|
||||||
tasks:
|
|
||||||
- build: |
|
|
||||||
cd shadow
|
|
||||||
./autogen.sh --without-selinux --disable-man --disable-nls
|
|
||||||
grep ENABLE_ config.status
|
|
||||||
- tasks: |
|
|
||||||
cd shadow
|
|
||||||
cat /proc/self/uid_map
|
|
||||||
cat /proc/self/status
|
|
||||||
make
|
|
||||||
make DESTDIR=/tmp/shadow-inst install
|
|
||||||
sudo make install
|
|
||||||
#TODO - fix up the tests. Let's merge what's here now as it
|
|
||||||
#at least tests build.
|
|
||||||
#(cd tests; sudo ./run_some || { cat testsuite.log; false; })
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
image: fedora/latest
|
|
||||||
packages:
|
|
||||||
- autoconf
|
|
||||||
- automake
|
|
||||||
- byacc
|
|
||||||
- expect
|
|
||||||
- findutils
|
|
||||||
- gettext
|
|
||||||
- gettext-devel
|
|
||||||
- git
|
|
||||||
- libbsd-devel
|
|
||||||
- libselinux-devel
|
|
||||||
- libsemanage-devel
|
|
||||||
- libtool
|
|
||||||
- libxslt
|
|
||||||
- pkgconf
|
|
||||||
sources:
|
|
||||||
- https://github.com/shadow-maint/shadow
|
|
||||||
tasks:
|
|
||||||
- build: |
|
|
||||||
cd shadow
|
|
||||||
./autogen.sh --with-selinux --enable-man
|
|
||||||
grep ENABLE_ config.status
|
|
||||||
- tasks: |
|
|
||||||
cd shadow
|
|
||||||
cat /proc/self/uid_map
|
|
||||||
cat /proc/self/status
|
|
||||||
make
|
|
||||||
make DESTDIR=/tmp/shadow-inst install
|
|
||||||
sudo make install
|
|
||||||
#TODO - fix up the tests. Let's merge what's here now as it
|
|
||||||
#at least tests build.
|
|
||||||
#(cd tests; sudo ./run_some || { cat testsuite.log; false; })
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
image: ubuntu/focal
|
|
||||||
packages:
|
|
||||||
- automake
|
|
||||||
- autopoint
|
|
||||||
- xsltproc
|
|
||||||
- libbsd-dev
|
|
||||||
- libselinux1-dev
|
|
||||||
- gettext
|
|
||||||
- expect
|
|
||||||
- byacc
|
|
||||||
- libtool
|
|
||||||
- pkgconf
|
|
||||||
sources:
|
|
||||||
- https://github.com/shadow-maint/shadow
|
|
||||||
tasks:
|
|
||||||
- build: |
|
|
||||||
cd shadow
|
|
||||||
./autogen.sh --without-selinux --disable-man
|
|
||||||
grep ENABLE_ config.status
|
|
||||||
- tasks: |
|
|
||||||
cd shadow
|
|
||||||
cat /proc/self/uid_map
|
|
||||||
cat /proc/self/status
|
|
||||||
systemd-detect-virt
|
|
||||||
make
|
|
||||||
make DESTDIR=/tmp/shadow-inst install
|
|
||||||
sudo make install
|
|
||||||
(cd tests; sudo ./run_some || { cat testsuite.log; false; })
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
image: ubuntu/22.04
|
|
||||||
packages:
|
|
||||||
- automake
|
|
||||||
- autopoint
|
|
||||||
- xsltproc
|
|
||||||
- libbsd-dev
|
|
||||||
- libselinux1-dev
|
|
||||||
- gettext
|
|
||||||
- expect
|
|
||||||
- byacc
|
|
||||||
- libtool
|
|
||||||
- pkgconf
|
|
||||||
sources:
|
|
||||||
- https://github.com/shadow-maint/shadow
|
|
||||||
tasks:
|
|
||||||
- build: |
|
|
||||||
cd shadow
|
|
||||||
./autogen.sh --without-selinux --enable-man
|
|
||||||
grep ENABLE_ config.status
|
|
||||||
- tasks: |
|
|
||||||
cat /proc/self/uid_map
|
|
||||||
cat /proc/self/status
|
|
||||||
systemd-detect-virt
|
|
||||||
cd shadow
|
|
||||||
make
|
|
||||||
make DESTDIR=/tmp/shadow-inst install
|
|
||||||
sudo make install
|
|
||||||
(cd tests; sudo ./run_some || { cat testsuite.log; false; })
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*.{c,h}]
|
|
||||||
indent_style = tab
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
name: 'Install dependencies'
|
|
||||||
description: 'Install dependencies to build shadow-utils'
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y ubuntu-dev-tools libbsd-dev
|
|
||||||
sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get -y build-dep shadow
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: debug
|
|
||||||
run: |
|
|
||||||
id
|
|
||||||
which bash
|
|
||||||
whoami
|
|
||||||
env
|
|
||||||
ps -ef
|
|
||||||
pwd
|
|
||||||
cat /proc/self/uid_map
|
|
||||||
cat /proc/self/status
|
|
||||||
systemd-detect-virt
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo cat /etc/apt/sources.list
|
|
||||||
sudo sed -i '/deb-src/d' /etc/apt/sources.list
|
|
||||||
sudo sed -i '/^deb /p;s/ /-src /' /etc/apt/sources.list
|
|
||||||
export DEBIAN_PRIORITY=critical
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
# let's try to work around upgrade breakage in a pkg we don't care about
|
|
||||||
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y dist-upgrade
|
|
||||||
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev pkgconf
|
|
||||||
sudo apt-get -y build-dep shadow
|
|
||||||
- name: configure
|
|
||||||
run: |
|
|
||||||
autoreconf -v -f --install
|
|
||||||
./autogen.sh --without-selinux --disable-man --with-yescrypt
|
|
||||||
- run: make
|
|
||||||
- run: make install DESTDIR=${HOME}/rootfs
|
|
||||||
- run: sudo make install
|
|
||||||
- name: run tests in shell with tty
|
|
||||||
shell: 'script -q -e -c "bash {0}"'
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
cd tests
|
|
||||||
sudo ./run_some
|
|
||||||
cat testsuite.log
|
|
||||||
|
|
||||||
# Make sure that 'make dist' makes a usable tarball with no missing files
|
|
||||||
dist-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo cat /etc/apt/sources.list
|
|
||||||
sudo sed -i '/deb-src/d' /etc/apt/sources.list
|
|
||||||
sudo sed -i '/^deb /p;s/ /-src /' /etc/apt/sources.list
|
|
||||||
export DEBIAN_PRIORITY=critical
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
# let's try to work around upgrade breakage in a pkg we don't care about
|
|
||||||
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y dist-upgrade
|
|
||||||
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev pkgconf
|
|
||||||
sudo apt-get -y build-dep shadow
|
|
||||||
|
|
||||||
- name: Test make dist
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
make dist
|
|
||||||
f=shadow-*.tar.gz
|
|
||||||
tar -zxf $f
|
|
||||||
d=$(basename $f .tar.gz)
|
|
||||||
cd $d
|
|
||||||
./configure
|
|
||||||
make -j5
|
|
||||||
|
|
||||||
container-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [alpine, debian, fedora]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Build container
|
|
||||||
run: |
|
|
||||||
docker buildx build -f ./share/containers/${{ matrix.os }}.dockerfile . --output build-out
|
|
||||||
|
|
||||||
- name: Store artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.os }}-build
|
|
||||||
path: |
|
|
||||||
./build-out/config.log
|
|
||||||
./build-out/config.h
|
|
||||||
if-no-files-found: ignore
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
name: "Static code analysis"
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
schedule:
|
|
||||||
# Everyday at midnight
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
jobs:
|
|
||||||
codeql:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
security-events: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
id: dependencies
|
|
||||||
uses: ./.github/actions/install-dependencies
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
languages: cpp
|
|
||||||
queries: +security-and-quality
|
|
||||||
|
|
||||||
- name: Configure shadow-utils
|
|
||||||
run: ./autogen.sh --without-selinux --disable-man
|
|
||||||
|
|
||||||
- name: Build shadow-utils
|
|
||||||
run: |
|
|
||||||
PROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
|
||||||
make -kj$PROCESSORS || true
|
|
||||||
|
|
||||||
- name: Check build errors
|
|
||||||
run: make
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
||||||
|
|
||||||
differential-shellcheck:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# Doc: https://github.com/redhat-plumbers-in-action/differential-shellcheck#usage
|
|
||||||
- name: Differential ShellCheck
|
|
||||||
uses: redhat-plumbers-in-action/differential-shellcheck@v3
|
|
||||||
with:
|
|
||||||
severity: warning
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
-51
@@ -1,51 +0,0 @@
|
|||||||
*~
|
|
||||||
lib*.a
|
|
||||||
*.o
|
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
*.gmo
|
|
||||||
.deps
|
|
||||||
.libs
|
|
||||||
|
|
||||||
*.patch
|
|
||||||
*.rej
|
|
||||||
*.orig
|
|
||||||
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
|
|
||||||
/ABOUT-NLS
|
|
||||||
/aclocal.m4
|
|
||||||
/autom4te.cache
|
|
||||||
/compile
|
|
||||||
/config.cache
|
|
||||||
/config.guess
|
|
||||||
/config.h
|
|
||||||
/config.h.in
|
|
||||||
/config.log
|
|
||||||
/config.rpath
|
|
||||||
/config.status
|
|
||||||
/config.sub
|
|
||||||
/configure
|
|
||||||
/depcomp
|
|
||||||
/install-sh
|
|
||||||
/libtool
|
|
||||||
/ltmain.sh
|
|
||||||
/m4
|
|
||||||
/missing
|
|
||||||
/stamp-h1
|
|
||||||
/ylwrap
|
|
||||||
|
|
||||||
/po/*.header
|
|
||||||
/po/*.sed
|
|
||||||
/po/*.sin
|
|
||||||
/po/Makefile.in.in
|
|
||||||
/po/Makevars.template
|
|
||||||
/po/POTFILES
|
|
||||||
/po/Rules-quot
|
|
||||||
/po/stamp-po
|
|
||||||
|
|
||||||
/shadow.spec
|
|
||||||
/shadow-*.tar.*
|
|
||||||
/lib/getdate.c
|
|
||||||
/libsubid/subid.h
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
dist: bionic
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
language: c
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
|
|
||||||
arch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
- ppc64le
|
|
||||||
- s390x
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get update -qq
|
|
||||||
- sudo apt-get -y install -qq automake autopoint xsltproc libselinux1-dev gettext expect
|
|
||||||
- sudo apt-get -y install -qq byacc libtool
|
|
||||||
script:
|
|
||||||
- ./autogen.sh --without-selinux --disable-man
|
|
||||||
- grep ENABLE_ config.status
|
|
||||||
- make
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- secure: "G47VYFrtzqalrVjixTqBG9Qsa8EZRcaqsh1k6fq5JgEyHmMQActpvTUDs9FXf1MEqiY5XX3VDVfBsZgKPHgmHsMzD1bX11xpnpGByB8g7gr8I3u2ZkCREqgi77a5l3LeBh+seWiambe/DYOgvPCNa6pCynLgR9advqtgKhpCruU="
|
|
||||||
|
|
||||||
addons:
|
|
||||||
coverity_scan:
|
|
||||||
|
|
||||||
project:
|
|
||||||
name: "shadow-maint/shadow"
|
|
||||||
description: "Upstream shadow utils tree"
|
|
||||||
|
|
||||||
notification_email: christian.brauner@ubuntu.com,serge@hallyn.com
|
|
||||||
|
|
||||||
build_command_prepend: "./autogen.sh --without-selinux --disable-man"
|
|
||||||
build_command: "make -kj4 || make"
|
|
||||||
branch_pattern: master
|
|
||||||
|
|
||||||
script:
|
|
||||||
- cat /proc/self/uid_map
|
|
||||||
- cat /proc/self/status
|
|
||||||
- systemd-detect-virt
|
|
||||||
- ./autogen.sh --without-selinux --disable-man
|
|
||||||
- grep ENABLE_ config.status
|
|
||||||
- make
|
|
||||||
- sudo make install
|
|
||||||
- (cd tests; sudo ./run_some; cat testsuite.log)
|
|
||||||
|
|
||||||
# vim:et:ts=2:sw=2
|
|
||||||
-90
@@ -1,90 +0,0 @@
|
|||||||
Thanks to at least the following people for sending patches, bug
|
|
||||||
reports and various comments. This list may be incomplete, I received
|
|
||||||
a lot of mail...
|
|
||||||
|
|
||||||
# Maintainers
|
|
||||||
* Marek Michałkiewicz <marekm72@gmail.com> (1995-2000)
|
|
||||||
* Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2007)
|
|
||||||
* Nicolas François <nicolas.francois@centraliens.net> (2007-2014)
|
|
||||||
* Serge E. Hallyn <serge@hallyn.com> (2014-now)
|
|
||||||
* Christian Brauner <christian@brauner.io> (2019-now)
|
|
||||||
* Iker Pedrosa <ipedrosa@redhat.com> (2022-now)
|
|
||||||
|
|
||||||
# Authors and contributors
|
|
||||||
* Adam Rudnicki <adam@v-lo.krakow.pl>
|
|
||||||
* Alan Curry <pacman@tardis.mars.net>
|
|
||||||
* Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
* Alexander O. Yuriev <alex@bach.cis.temple.edu>
|
|
||||||
* Algis Rudys <arudys@rice.edu>
|
|
||||||
* Andreas Jaeger <aj@arthur.rhein-neckar.de>
|
|
||||||
* Andy Zaugg <andy.zaugg@gmail.com>
|
|
||||||
* Aniello Del Sorbo <anidel@edu-gw.dia.unisa.it>
|
|
||||||
* Anton Gluck <gluc@midway.uchicago.edu>
|
|
||||||
* Arkadiusz Miskiewicz <misiek@pld.org.pl>
|
|
||||||
* Ben Collins <bcollins@debian.org>
|
|
||||||
* Brian R. Gaeke <brg@dgate.org>
|
|
||||||
* Calle Karlsson <ckn@kash.se>
|
|
||||||
* Chip Rosenthal <chip@unicom.com>
|
|
||||||
* Chris Evans <lady0110@sable.ox.ac.uk>
|
|
||||||
* Chris Lamb <chris@chris-lamb.co.uk>
|
|
||||||
* Cristian Gafton <gafton@sorosis.ro>
|
|
||||||
* Dan Walsh <dwalsh@redhat.com>
|
|
||||||
* Darcy Boese <possum@chardonnay.niagara.com>
|
|
||||||
* Dave Hagewood <admin@arrowweb.com>
|
|
||||||
* David A. Holland <dholland@hcs.harvard.edu>
|
|
||||||
* David Frey <David.Frey@lugs.ch>
|
|
||||||
* Ed Carp <ecarp@netcom.com>
|
|
||||||
* Ed Neville <ed@s5h.net>
|
|
||||||
* Eric W. Biederman" <ebiederm@xmission.com>
|
|
||||||
* Floody <flood@evcom.net>
|
|
||||||
* Frank Denis <j@4u.net>
|
|
||||||
* George Kraft IV <gk4@us.ibm.com>
|
|
||||||
* Greg Mortensen <loki@world.std.com>
|
|
||||||
* Guido van Rooij
|
|
||||||
* Guy Maor <maor@debian.org>
|
|
||||||
* Hrvoje Dogan <hdogan@bjesomar.srce.hr>
|
|
||||||
* Jakub Hrozek <jhrozek@redhat.com>
|
|
||||||
* Janos Farkas <chexum@bankinf.banki.hu>
|
|
||||||
* Jason Franklin <jason.franklin@quoininc.com>
|
|
||||||
* Jay Soffian <jay@lw.net>
|
|
||||||
* Jesse Thilo <Jesse.Thilo@pobox.com>
|
|
||||||
* Joey Hess <joey@kite.ml.org>
|
|
||||||
* John Adelsberger <jja@umr.edu>
|
|
||||||
* Jonathan Hankins <jhankins@mailserv.homewood.k12.al.us>
|
|
||||||
* Jon Lewis <jlewis@lewis.org>
|
|
||||||
* Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
|
|
||||||
* Judd Bourgeois <shagboy@bluesky.net>
|
|
||||||
* Juergen Heinzl <unicorn@noris.net>
|
|
||||||
* Juha Virtanen <jiivee@iki.fi>
|
|
||||||
* Julian Pidancet <julian.pidancet@gmail.com>
|
|
||||||
* Julianne Frances Haugh <julie78787@gmail.com>
|
|
||||||
* Leonard N. Zubkoff <lnz@dandelion.com>
|
|
||||||
* Luca Berra <bluca@www.polimi.it>
|
|
||||||
* Lukáš Kuklínek <lkukline@redhat.com>
|
|
||||||
* Lutz Schwalowsky <schwalow@mineralogie.uni-hamburg.de>
|
|
||||||
* Marc Ewing <marc@redhat.com>
|
|
||||||
* Martin Bene <mb@sime.com>
|
|
||||||
* Martin Mares <mj@gts.cz>
|
|
||||||
* Michael Meskes <meskes@topsystem.de>
|
|
||||||
* Michael Talbot-Wilson <mike@calypso.bns.com.au>
|
|
||||||
* Michael Vetter <jubalh@iodoru.org>
|
|
||||||
* Mike Frysinger <vapier@gentoo.org>
|
|
||||||
* Mike Pakovic <mpakovic@users.southeast.net>
|
|
||||||
* Nicolas François <nicolas.francois@centraliens.net>
|
|
||||||
* Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
|
|
||||||
* Pavel Machek <pavel@bug.ucw.cz>
|
|
||||||
* Peter Vrabec <pvrabec@redhat.com>
|
|
||||||
* Phillip Street
|
|
||||||
* Rafał Maszkowski <rzm@icm.edu.pl>
|
|
||||||
* Rani Chouha <ranibey@smartec.com>
|
|
||||||
* Sami Kerola <kerolasa@rocketmail.com>
|
|
||||||
* Scott Garman <scott.a.garman@intel.com>
|
|
||||||
* Sebastian Rick Rijkers <srrijkers@gmail.com>
|
|
||||||
* Seraphim Mellos <mellos@ceid.upatras.gr>
|
|
||||||
* Shane Watts <shane@nexus.mlckew.edu.au>
|
|
||||||
* Steve M. Robbins <steve@nyongwa.montreal.qc.ca>
|
|
||||||
* Thorsten Kukuk <kukuk@suse.de>
|
|
||||||
* Tim Hockin <thockin@eagle.ais.net>
|
|
||||||
* Timo Karjalainen <timok@iki.fi>
|
|
||||||
* Ulisses Alonso Camaro <ulisses@pusa.eleinf.uv.es>
|
|
||||||
* Werner Fink <werner@suse.de>
|
|
||||||
@@ -1,41 +1,118 @@
|
|||||||
SPDX-License-Identifier: BSD-3-Clause
|
NOTE:
|
||||||
|
This license has been obsoleted by the change to the BSD-style copyright.
|
||||||
|
You may continue to use this license if you wish, but you are under no
|
||||||
|
obligation to do so.
|
||||||
|
|
||||||
All files under this project either
|
(*
|
||||||
|
This document is freely plagiarised from the 'Artistic Licence',
|
||||||
|
distributed as part of the Perl v4.0 kit by Larry Wall, which is
|
||||||
|
available from most major archive sites. I stole it from CrackLib.
|
||||||
|
|
||||||
1. fall under the BSD 3 clause license (by default).
|
$Id$
|
||||||
|
*)
|
||||||
|
|
||||||
2. carry an SPDX header declaring what license applies.
|
This documents purpose is to state the conditions under which this
|
||||||
|
Package (See definition below) viz: "Shadow", the Shadow Password Suite
|
||||||
|
which is held by Julianne Frances Haugh, may be copied, such that the
|
||||||
|
copyright holder maintains some semblance of artistic control over the
|
||||||
|
development of the package, while giving the users of the package the
|
||||||
|
right to use and distribute the Package in a more-or-less customary
|
||||||
|
fashion, plus the right to make reasonable modifications.
|
||||||
|
|
||||||
or
|
So there.
|
||||||
|
|
||||||
3. list a full custom license
|
***************************************************************************
|
||||||
|
|
||||||
This software is originally
|
Definitions:
|
||||||
|
|
||||||
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
|
|
||||||
|
|
||||||
* All rights reserved.
|
A "Package" refers to the collection of files distributed by the
|
||||||
*
|
Copyright Holder, and derivatives of that collection of files created
|
||||||
* Redistribution and use in source and binary forms, with or without
|
through textual modification, or segments thereof.
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
"Standard Version" refers to such a Package if it has not been modified,
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
or has been modified in accordance with the wishes of the Copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
Holder.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
"Copyright Holder" is whoever is named in the copyright or copyrights
|
||||||
* documentation and/or other materials provided with the distribution.
|
for the package.
|
||||||
* 3. The name of the copyright holders or contributors may not be used to
|
|
||||||
* endorse or promote products derived from this software without
|
"You" is you, if you're thinking about copying or distributing this
|
||||||
* specific prior written permission.
|
Package.
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
"Reasonable copying fee" is whatever you can justify on the basis of
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
media cost, duplication charges, time of people involved, and so on.
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
(You will not be required to justify it to the Copyright Holder, but
|
||||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
only to the computing community at large as a market that must bear the
|
||||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
fee.)
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
"Freely Available" means that no fee is charged for the item itself,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
though there may be fees involved in handling the item. It also means
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
that recipients of the item may redistribute it under the same
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
conditions they received it.
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
|
1. You may make and give away verbatim copies of the source form of the
|
||||||
|
Standard Version of this Package without restriction, provided that you
|
||||||
|
duplicate all of the original copyright notices and associated
|
||||||
|
disclaimers.
|
||||||
|
|
||||||
|
2. You may apply bug fixes, portability fixes and other modifications
|
||||||
|
derived from the Public Domain or from the Copyright Holder. A Package
|
||||||
|
modified in such a way shall still be considered the Standard Version.
|
||||||
|
|
||||||
|
3. You may otherwise modify your copy of this Package in any way,
|
||||||
|
provided that you insert a prominent notice in each changed file stating
|
||||||
|
how and when AND WHY you changed that file, and provided that you do at
|
||||||
|
least ONE of the following:
|
||||||
|
|
||||||
|
a) place your modifications in the Public Domain or otherwise make them
|
||||||
|
Freely Available, such as by posting said modifications to Usenet or an
|
||||||
|
equivalent medium, or placing the modifications on a major archive site
|
||||||
|
such as uunet.uu.net, or by allowing the Copyright Holder to include
|
||||||
|
your modifications in the Standard Version of the Package.
|
||||||
|
|
||||||
|
b) use the modified Package only within your corporation or organization.
|
||||||
|
|
||||||
|
c) rename any non-standard executables so the names do not conflict with
|
||||||
|
standard executables, which must also be provided, and provide separate
|
||||||
|
documentation for each non-standard executable that clearly documents
|
||||||
|
how it differs from the Standard Version.
|
||||||
|
|
||||||
|
d) make other distribution arrangements with the Copyright Holder.
|
||||||
|
|
||||||
|
4. You may distribute the programs of this Package in object code or
|
||||||
|
executable form, provided that you do at least ONE of the following:
|
||||||
|
|
||||||
|
a) distribute a Standard Version of the executables and library files,
|
||||||
|
together with instructions (in the manual page or equivalent) on where
|
||||||
|
to get the Standard Version.
|
||||||
|
|
||||||
|
b) accompany the distribution with the machine-readable source of the
|
||||||
|
Package with your modifications.
|
||||||
|
|
||||||
|
c) accompany any non-standard executables with their corresponding
|
||||||
|
Standard Version executables, giving the non-standard executables
|
||||||
|
non-standard names, and clearly documenting the differences in manual
|
||||||
|
pages (or equivalent), together with instructions on where to get the
|
||||||
|
Standard Version.
|
||||||
|
|
||||||
|
d) make other distribution arrangements with the Copyright Holder.
|
||||||
|
|
||||||
|
5. You may charge a reasonable copying fee for any distribution of this
|
||||||
|
Package. You may charge any fee you choose for support of this Package.
|
||||||
|
YOU MAY NOT CHARGE A FEE FOR THIS PACKAGE ITSELF. However, you may
|
||||||
|
distribute this Package in aggregate with other (possibly commercial)
|
||||||
|
programs as part of a larger (possibly commercial) software distribution
|
||||||
|
provided that YOU DO NOT ADVERTISE this package as a product of your
|
||||||
|
own.
|
||||||
|
|
||||||
|
6. The name of the Copyright Holder may not be used to endorse or
|
||||||
|
promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
The End
|
||||||
|
|||||||
+3
-10
@@ -2,14 +2,7 @@
|
|||||||
|
|
||||||
EXTRA_DIST = NEWS README TODO shadow.spec.in
|
EXTRA_DIST = NEWS README TODO shadow.spec.in
|
||||||
|
|
||||||
SUBDIRS = lib
|
AUTOMAKE_OPTIONS = 1.5 dist-bzip2 foreign
|
||||||
|
|
||||||
if ENABLE_SUBIDS
|
SUBDIRS = po man libmisc lib src \
|
||||||
SUBDIRS += libsubid
|
contrib doc etc
|
||||||
endif
|
|
||||||
|
|
||||||
SUBDIRS += src po contrib doc etc
|
|
||||||
|
|
||||||
if ENABLE_REGENERATE_MAN
|
|
||||||
SUBDIRS += man
|
|
||||||
endif
|
|
||||||
|
|||||||
@@ -1,450 +1,5 @@
|
|||||||
$Id$
|
$Id$
|
||||||
|
|
||||||
shadow-4.1.5.1 -> shadow-4.2 UNRELEASED
|
|
||||||
|
|
||||||
*** general
|
|
||||||
* Handle libc whose crypt() returns NULL when passed a salt that
|
|
||||||
violates specs or system requirements (e.g. FIPS140). This is needed
|
|
||||||
with glibc/eglibc 2.17 for tools checking passwords (passwd (non PAM
|
|
||||||
enabled) or newgrp), and for tools generating encrypted passwords
|
|
||||||
(chgpasswd, chpasswd, or gpasswd when non PAM enabled or when a fixed
|
|
||||||
crypt method is requested on the command line, and newusers, or passwd
|
|
||||||
in their non PAM enabled versions)
|
|
||||||
* Fix segfault when reading groups split on multiple lines. This impacts
|
|
||||||
most user/group management tools when MAX_MEMBERS_PER_GROUP is set.
|
|
||||||
|
|
||||||
- su
|
|
||||||
* When su receives a signal (SIGTERM, or SIGINT/SIGQUIT in non
|
|
||||||
interactive mode), kill the child process group, rather than just the
|
|
||||||
immediate child.
|
|
||||||
* Fix segmentation faults for users without a proper home or shell in
|
|
||||||
their passwd entries.
|
|
||||||
|
|
||||||
- login
|
|
||||||
* Fix segmentation faults for users without a proper home or shell in
|
|
||||||
their passwd entries.
|
|
||||||
|
|
||||||
*** documentation
|
|
||||||
* Fixed useradd man page (--home-dir option, instead of --home).
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
* Updated Russian translation.
|
|
||||||
* Updated German man pages translation.
|
|
||||||
* Fixed gshadow Japanese man page translation.
|
|
||||||
|
|
||||||
shadow-4.1.5 -> shadow-4.1.5.1 2012-05-25
|
|
||||||
|
|
||||||
- login
|
|
||||||
* Log into utmp(x) when PAM is enabled, but do not log into wtmp.
|
|
||||||
This complete pam_lastlog which logs into wtmp and in into utmp(x).
|
|
||||||
- su
|
|
||||||
* non PAM enabled versions: do not fail if su is called without a
|
|
||||||
controlling terminal.
|
|
||||||
- userdel
|
|
||||||
* Fix segfault when userdel removes the user's group.
|
|
||||||
|
|
||||||
*** documentation
|
|
||||||
* .so links now point to paths relative to the top-level manual hierarchy
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
* Updated French man pages translation.
|
|
||||||
* Updated German man pages translation.
|
|
||||||
* Updated Polish man pages translation. (logoutd.8)
|
|
||||||
|
|
||||||
shadow-4.1.4.3 -> shadow-4.1.5 2012-02-12
|
|
||||||
|
|
||||||
*** security
|
|
||||||
* su -c could be abused by the executed command to invoke commands with
|
|
||||||
the caller privileges. See below. (CVE-2005-4890)
|
|
||||||
|
|
||||||
*** general
|
|
||||||
* report usage error to stderr, but report usage help to stdout (and return
|
|
||||||
zero) when explicitly requested (e.g. with --help).
|
|
||||||
* initial support for tcb (http://openwall.com/tcb/) for useradd,
|
|
||||||
userdel, usermod, chage, pwck, vipw.
|
|
||||||
* Added support for ACLs and Extended Attributes in useradd and usermod.
|
|
||||||
Support shall be enabled with the new --with-acl or --with-attr
|
|
||||||
configure options.
|
|
||||||
* Added diagnosis for lock failures.
|
|
||||||
* use libsemanage instead of the semanage tool.
|
|
||||||
|
|
||||||
- chage
|
|
||||||
* Add --root option.
|
|
||||||
- chfn
|
|
||||||
* Add --root option.
|
|
||||||
- chgpasswd
|
|
||||||
* When the gshadow file exists but there are no gshadow entries, an entry
|
|
||||||
is created if the password is changed and group requires a
|
|
||||||
shadow entry.
|
|
||||||
* Add --root option.
|
|
||||||
- chpasswd
|
|
||||||
* PAM enabled versions: restore the -e option to allow restoring
|
|
||||||
passwords without knowing those passwords. Restore together the -m
|
|
||||||
and -c options. (These options were removed in shadow-4.1.4 on PAM
|
|
||||||
enabled versions)
|
|
||||||
* When the shadow file exists but there are no shadow entries, an entry
|
|
||||||
is created if the password is changed and passwd requires a
|
|
||||||
shadow entry.
|
|
||||||
* Add --root option.
|
|
||||||
- chsh
|
|
||||||
* Add --root option.
|
|
||||||
- faillog
|
|
||||||
* The -l, -m, -r, -t options only act on the existing users, unless -a is
|
|
||||||
specified.
|
|
||||||
* Add --root option.
|
|
||||||
- gpasswd
|
|
||||||
* Add --root option.
|
|
||||||
- groupadd
|
|
||||||
* Add --root option.
|
|
||||||
- groupdel
|
|
||||||
* Add --root option.
|
|
||||||
- groupmems
|
|
||||||
* Fix parsing of gshadow entries.
|
|
||||||
* Add --root option.
|
|
||||||
- groupmod
|
|
||||||
* Fixed groupmod when configured with --enable-account-tools-setuid.
|
|
||||||
* When the gshadow file exists but there are no gshadow entries, an entry
|
|
||||||
is created if the password is changed and group requires a
|
|
||||||
shadow entry.
|
|
||||||
* Add --root option.
|
|
||||||
- grpck
|
|
||||||
* Add --root option.
|
|
||||||
* NIS entries were dropped by -s (sort).
|
|
||||||
- grpconv
|
|
||||||
* Add --root option.
|
|
||||||
- grpunconv
|
|
||||||
* Add --root option.
|
|
||||||
- lastlog
|
|
||||||
* Add --root option.
|
|
||||||
- login
|
|
||||||
* Fixed limits support (non PAM enabled versions only)
|
|
||||||
* Added support for infinite limits and group based limits (non PAM
|
|
||||||
enabled versions only)
|
|
||||||
* Fixed infinite loop when CONSOLE is configured with a colon-separated
|
|
||||||
list of TTYs.
|
|
||||||
* Fixed warning and support for CONSOLE_GROUPS for users member of more
|
|
||||||
than 16 groups.
|
|
||||||
* Do not log into utmp(x) or wtmp when PAM is enabled. This is done by
|
|
||||||
pam_lastlog.
|
|
||||||
- newgrp, sg
|
|
||||||
* Fix parsing of gshadow entries.
|
|
||||||
- newusers
|
|
||||||
* Add --root option.
|
|
||||||
- passwd
|
|
||||||
* Add --root option.
|
|
||||||
- pwpck
|
|
||||||
* NIS entries were dropped by -s (sort).
|
|
||||||
* Add --root option.
|
|
||||||
- pwconv
|
|
||||||
* Add --root option.
|
|
||||||
- pwunconv
|
|
||||||
* Add --root option.
|
|
||||||
- useradd
|
|
||||||
* If the skeleton directory contained hardlinked files, copies of the
|
|
||||||
hardlink were removed from the skeleton directory.
|
|
||||||
* Add --root option.
|
|
||||||
- userdel
|
|
||||||
* Check the existence of the user's mail spool before trying to remove
|
|
||||||
it. If it does not exist, a warning is issued, but no failure.
|
|
||||||
* Do not remove a group with the same name as the user (usergroup) if
|
|
||||||
this group isn't the user's primary group.
|
|
||||||
* Add --root option.
|
|
||||||
* Add --selinux-user option.
|
|
||||||
- usermod
|
|
||||||
* Accept options in any order (username not necessarily at the end)
|
|
||||||
* When the shadow file exists but there are no shadow entries, an entry
|
|
||||||
is created if the password is changed and passwd requires a
|
|
||||||
shadow entry, or if aging features are used (-e or -f).
|
|
||||||
* Add --root option.
|
|
||||||
- su
|
|
||||||
* Document the su exit values.
|
|
||||||
* When su receives a signal, wait for the child to terminate (after
|
|
||||||
sending a SIGTERM), and kill it only if it did not terminate by itself.
|
|
||||||
No delay will be enforced if the child cooperates.
|
|
||||||
* Default ENV_SUPATH is /sbin:/bin:/usr/sbin:/usr/bin
|
|
||||||
* Fixed infinite loop when CONSOLE is configured with a colon-separated
|
|
||||||
list of TTYs.
|
|
||||||
* Fixed warning and support for CONSOLE_GROUPS for users member of more
|
|
||||||
than 16 groups.
|
|
||||||
* Do not forward the controlling terminal to commands executed with -c.
|
|
||||||
This prevents tty hijacking which could lead to execution with the
|
|
||||||
caller's privileges.
|
|
||||||
* Close PAM sessions as root. This will be more friendly to PAM modules
|
|
||||||
like pam_mount or pam_systemd.
|
|
||||||
* Added support for PAM modules which change PAM_USER.
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
* Updated Brazilian Portuguese translation.
|
|
||||||
* Updated Catalan translation.
|
|
||||||
* Updated Czech translation.
|
|
||||||
* Updated Danish translation.
|
|
||||||
* New Danish man pages translation.
|
|
||||||
* Updated French translation.
|
|
||||||
* Updated French man pages translation.
|
|
||||||
* Updated German translation.
|
|
||||||
* Updated German man pages translation.
|
|
||||||
* Updated Greek translation.
|
|
||||||
* Updated Italian man pages translation.
|
|
||||||
* Updated Japanese translation.
|
|
||||||
* Updated Kazakh translation.
|
|
||||||
* Updated Norwegian Bokmål translation.
|
|
||||||
* Updated Portuguese translation.
|
|
||||||
* Updated Russian translation.
|
|
||||||
* Updated Simplified Chinese translation.
|
|
||||||
* Updated Simplified Chinese man pages translation.
|
|
||||||
* Updated Swedish translation.
|
|
||||||
* Updated Vietnamese translation.
|
|
||||||
|
|
||||||
shadow-4.1.4.2 -> shadow-4.1.4.3 2011-02-15
|
|
||||||
|
|
||||||
*** security
|
|
||||||
- CVE-2011-0721: An insufficient input sanitation in chfn can be exploited
|
|
||||||
to create users or groups in a NIS environment.
|
|
||||||
|
|
||||||
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
|
|
||||||
|
|
||||||
- general
|
|
||||||
* Improved support for large groups (impacts most user/group management
|
|
||||||
tools).
|
|
||||||
|
|
||||||
- addition of system users or groups
|
|
||||||
* Speed improvement. This should be noticeable in case of LDAP configured
|
|
||||||
systems. This should impact useradd, groupadd, and newusers
|
|
||||||
* Since system accounts are allocated from SYS_?ID_MIN to SYS_?ID_MAX in
|
|
||||||
reverse order, accounts are packed close to SYS_?ID_MAX if SYS_?ID_MIN
|
|
||||||
is already used but there are still dome gaps.
|
|
||||||
|
|
||||||
- login
|
|
||||||
* Add support for shells being a shell script without a shebang.
|
|
||||||
- su
|
|
||||||
* Preserve the DISPLAY and XAUTHORITY environment variables. This was
|
|
||||||
only the case in the non PAM enabled versions.
|
|
||||||
* Add support for shells being a shell script without a shebang.
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
* The Finnish translation of passwd(1) was outdated and is no more
|
|
||||||
distributed.
|
|
||||||
|
|
||||||
shadow-4.1.4 -> shadow-4.1.4.1 2009-05-22
|
|
||||||
|
|
||||||
- login
|
|
||||||
* Fix failures with empty usernames on non PAM versions.
|
|
||||||
* Fix CONSOLE (securetty) support on non PAM versions.
|
|
||||||
- newgrp
|
|
||||||
* Return the exit status of the child.
|
|
||||||
- userdel
|
|
||||||
* On Linux, do not check if an user is logged in with utmp, but check if
|
|
||||||
the user is running some processes.
|
|
||||||
* If not on Linux, continue to search for an utmp record, but make sure
|
|
||||||
the process recorded in the utmp entry is still running.
|
|
||||||
* Report failures to remove the user's mailbox
|
|
||||||
* When USERGROUPS_ENAB is enabled, remove the user's group when the
|
|
||||||
user was the only member.
|
|
||||||
* Do not fail when -r is used and the home directory does not exist.
|
|
||||||
- usermod
|
|
||||||
* Check if the user is busy when the user's UID, name or home directory
|
|
||||||
is changed.
|
|
||||||
|
|
||||||
shadow-4.1.3.1 -> shadow-4.1.4 2009-05-10
|
|
||||||
|
|
||||||
- packaging
|
|
||||||
* Enable --enable-account-tools-setuid by default for PAM builds.
|
|
||||||
* Add configure option --enable-utmpx, disabled by default to mimic
|
|
||||||
the previous behavior on Linux (where utmp and utmpx are identical).
|
|
||||||
* Fix build failure on non-PAM systems when --without-pam is not
|
|
||||||
specified.
|
|
||||||
|
|
||||||
- chpasswd
|
|
||||||
* Change the passwords using PAM. This permits to define the password
|
|
||||||
policy in a central place. The -c/--crypt-method, -e/--encrypted,
|
|
||||||
-m/--md5 and -s/--sha-rounds options are no more supported on PAM
|
|
||||||
enabled systems.
|
|
||||||
- grpck
|
|
||||||
* Warn if a group has an entry in group and gshadow, and the password
|
|
||||||
field in group is not 'x'.
|
|
||||||
- login
|
|
||||||
* Do not trust the current utmp entry's ut_line to set PAM_TTY. This could
|
|
||||||
lead to DOS attacks.
|
|
||||||
* (PAM) Even if the user was already authenticated (-f flag), ask the
|
|
||||||
user to update his authentication token if needed.
|
|
||||||
- lastlog
|
|
||||||
* Fix regression causing empty reports.
|
|
||||||
- newusers
|
|
||||||
* Change the passwords using PAM. This permits to define the password
|
|
||||||
policy in a central place. The -c/--crypt-method and -s/--sha-rounds
|
|
||||||
options are no more supported on PAM enabled systems.
|
|
||||||
- pwck
|
|
||||||
* Warn if an user has an entry in passwd and shadow, and the password
|
|
||||||
field in passwd is not 'x'.
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
- Updated Czech translation
|
|
||||||
- Updated French translation
|
|
||||||
- Updated German translation
|
|
||||||
- Updated Japanese translation
|
|
||||||
- Updated Korean translation
|
|
||||||
- Updated Portuguese translation
|
|
||||||
- Updated Russian translation
|
|
||||||
|
|
||||||
shadow-4.1.3 -> shadow-4.1.3.1 2009-04-15
|
|
||||||
|
|
||||||
*** security:
|
|
||||||
- Due to bad parsing of octal permissions, the permissions on tty (login)
|
|
||||||
but also UMASK were set wrongly (and weirdly). Only shadow-4.1.3 was
|
|
||||||
affected.
|
|
||||||
|
|
||||||
*** general
|
|
||||||
- login
|
|
||||||
* Fix regression when no user is specified on the command line.
|
|
||||||
- userdel
|
|
||||||
* Fixed SE Linux support
|
|
||||||
- vipw
|
|
||||||
* SE Linux: Set the default context to the context of the file being
|
|
||||||
edited. This ensures that the backup file inherit from the file's
|
|
||||||
context.
|
|
||||||
|
|
||||||
*** translation
|
|
||||||
- Updated Norwegian Bokmål translation
|
|
||||||
|
|
||||||
shadow-4.1.2.2 -> shadow-4.1.3 2009-04-12
|
|
||||||
|
|
||||||
*** general:
|
|
||||||
- packaging
|
|
||||||
* Fixed support for OpenPAM.
|
|
||||||
* Fixed support for uclibc.
|
|
||||||
* Added configure --enable-account-tools-setuid (default) /
|
|
||||||
--disable-account-tools-setuid options. This permits to disable the
|
|
||||||
PAM authentication of the caller for chage, chgpasswd, chpasswd,
|
|
||||||
groupadd, groupdel, groupmod, newusers, useradd, userdel, and usermod.
|
|
||||||
This authentication is not necessary when these tools are not
|
|
||||||
installed setuid root.
|
|
||||||
* Added configure --with-group-name-max-length (default) /
|
|
||||||
--without-group-name-max-length options. This permits to configure the maximum length allowed for group names:
|
|
||||||
<no option> -> default of 16 (like today)
|
|
||||||
--with-group-name-max-length -> default of 16
|
|
||||||
--without-group-name-max-length -> no max length
|
|
||||||
--with-group-name-max-length=n > max is set to n
|
|
||||||
No sanity checking is performed on n so people could do
|
|
||||||
something neat like --with-group-name-max-length=MAX_INT
|
|
||||||
- addition of users or groups
|
|
||||||
* Speed improvement in case UID_MAX/SYS_UID_MAX/GID_MAX/SYS_GID_MAX is
|
|
||||||
used for an user/group. This should be noticeable in case of LDAP
|
|
||||||
configured systems. This should impact useradd, groupadd, and newusers
|
|
||||||
- error handling improvement
|
|
||||||
* Make sure errors and incomplete changes are reported to syslog and
|
|
||||||
audit in case of unexpected failures.
|
|
||||||
* Report system inconsistencies to syslog and audit.
|
|
||||||
* Only report success to syslog and audit if the changes are really
|
|
||||||
performed in the system databases.
|
|
||||||
This is still not complete.
|
|
||||||
- /etc/login.defs
|
|
||||||
* New CREATE_HOME variable to tell useradd to create a home directory by
|
|
||||||
default.
|
|
||||||
- Translations
|
|
||||||
* New Kazakh translation.
|
|
||||||
* Spanish manpages are no more distributed. They are outdated. Please
|
|
||||||
contact pkg-shadow-devel@lists.alioth.debian.org if you wish to
|
|
||||||
provide updates.
|
|
||||||
|
|
||||||
- faillog
|
|
||||||
* Accept users specified as a numerical UID, or ranges of users (-user,
|
|
||||||
user-, user1-user2).
|
|
||||||
* -l, -m, and -r now apply not only to existing users, but to all the
|
|
||||||
specified UIDs.
|
|
||||||
* Options can be specified in any order.
|
|
||||||
- gpasswd
|
|
||||||
* Added support for long options --add (-a), --delete (-d),
|
|
||||||
--remove-password (-r), --restrict (-R), --administrators (-A), and
|
|
||||||
--members (-M).
|
|
||||||
* Added support for usernames with arbitrary length.
|
|
||||||
* audit logging improvements.
|
|
||||||
* error handling improvement (see above).
|
|
||||||
* Log permission denied to syslog and audit.
|
|
||||||
- groupadd
|
|
||||||
* audit logging improvements.
|
|
||||||
* error handling improvement (see above).
|
|
||||||
* Speedup (see "addition of users or groups" above).
|
|
||||||
* do not create groups with GID set to (gid_t)-1.
|
|
||||||
* Allocate system group GIDs in reverse order. This could be useful
|
|
||||||
later to increase the static IDs range.
|
|
||||||
- groupdel
|
|
||||||
* audit logging improvements.
|
|
||||||
* error handling improvement (see above).
|
|
||||||
- groupmems
|
|
||||||
* Check if user exist before they are added to groups.
|
|
||||||
* Avoid segfault in case the specified group does not exist in /etc/group.
|
|
||||||
* Everybody is allowed to list the users of a group.
|
|
||||||
* /etc/group is open readonly when one just wants to list the users of a
|
|
||||||
group.
|
|
||||||
* Added syslog support.
|
|
||||||
* Use the groupmems PAM service name instead of groupmod.
|
|
||||||
* Fix segmentation faults when adding or removing users from a group.
|
|
||||||
* Added support for shadow groups.
|
|
||||||
* Added support long options --add (-a), --delete (-d), --purge (-p),
|
|
||||||
--list (-l), --group (-g).
|
|
||||||
- groupmod
|
|
||||||
* audit logging improvements.
|
|
||||||
* error handling improvement (see above).
|
|
||||||
* do not create groups with GID set to (gid_t)-1.
|
|
||||||
- grpck
|
|
||||||
* warn for groups with GID set to (gid_t)-1.
|
|
||||||
- login
|
|
||||||
* Restore the echoctl, echoke, onclr flags to the terminal termio flags.
|
|
||||||
Reset echoprt, noflsh, tostop. This behavior seems to have change by
|
|
||||||
mistake in earlier releases (4.0.8, for no obvious reason).
|
|
||||||
- newusers
|
|
||||||
* Implement the -r, --system option.
|
|
||||||
* Speedup (see "addition of users or groups" above).
|
|
||||||
* do not create users with UID set to (gid_t)-1.
|
|
||||||
* do not create groups with GID set to (gid_t)-1.
|
|
||||||
* Allocate system account UIDs/GIDs in reverse order. This could be useful
|
|
||||||
later to increase the static IDs range.
|
|
||||||
- passwd
|
|
||||||
* For compatibility with other passwd version, the --lock an --unlock
|
|
||||||
options do not lock or unlock the user account anymore. They only
|
|
||||||
lock or unlock the user's password.
|
|
||||||
- pwck
|
|
||||||
* warn for users with UID set to (uid_t)-1.
|
|
||||||
- su
|
|
||||||
* Preserve COLORTERM in addition to TERM when su is called with the -l
|
|
||||||
option.
|
|
||||||
- useradd
|
|
||||||
* audit logging improvements.
|
|
||||||
* Speedup (see "addition of users or groups" above).
|
|
||||||
* See CREATE_HOME above.
|
|
||||||
* New -M/--no-create-home option to disable CREATE_HOME.
|
|
||||||
* do not create users with UID set to (gid_t)-1.
|
|
||||||
* Added -Z option to map SELinux user for user's login.
|
|
||||||
* Allocate system user UIDs in reverse order. This could be useful
|
|
||||||
later to increase the static IDs range.
|
|
||||||
- userdel
|
|
||||||
* audit logging improvements.
|
|
||||||
* Do not fail if the removed user is not in the shadow database.
|
|
||||||
* When the user's group shall be removed, do not fail if this group is
|
|
||||||
not in the gshadow file.
|
|
||||||
* Delete the SELinux user mapping for user's login.
|
|
||||||
- usermod
|
|
||||||
* Allow adding LDAP users (or any user not present in the local passwd
|
|
||||||
file) to local groups
|
|
||||||
* do not create users with UID set to (gid_t)-1.
|
|
||||||
* Added -Z option to map SELinux user for user's login.
|
|
||||||
|
|
||||||
shadow-4.1.2.1 -> shadow-4.1.2.2 23-11-2008
|
|
||||||
|
|
||||||
*** security
|
|
||||||
- Fix a race condition in login that could lead to gaining ownership or
|
|
||||||
changing mode of arbitrary files.
|
|
||||||
- Fix a possible login DOS, which could be caused by injecting forged
|
|
||||||
entries in utmp.
|
|
||||||
|
|
||||||
shadow-4.1.2 -> shadow-4.1.2.1 26-06-2008
|
|
||||||
|
|
||||||
*** security
|
|
||||||
- Fix an "audit log injection" vulnerability in login.
|
|
||||||
This vulnerability makes it easier for attackers to hide activities by
|
|
||||||
modifying portions of log events, e.g. by appending an addr= statement
|
|
||||||
to the login name.
|
|
||||||
|
|
||||||
shadow-4.1.1 -> shadow-4.1.2 25-05-2008
|
shadow-4.1.1 -> shadow-4.1.2 25-05-2008
|
||||||
|
|
||||||
*** security:
|
*** security:
|
||||||
@@ -511,7 +66,7 @@ shadow-4.1.0 -> shadow-4.1.1 02-04-2008
|
|||||||
faillog faster.
|
faillog faster.
|
||||||
- gpasswd
|
- gpasswd
|
||||||
* Fix failures when the gshadow file is not present.
|
* Fix failures when the gshadow file is not present.
|
||||||
* When a password is moved to the gshadow file, use "x" instead of "!"
|
* When a password is moved to the gshadow file, use "x" instead of "x"
|
||||||
to indicate that the password is shadowed (consistency with grpconv).
|
to indicate that the password is shadowed (consistency with grpconv).
|
||||||
* Make sure the group and gshadow files are unlocked on exit.
|
* Make sure the group and gshadow files are unlocked on exit.
|
||||||
- groupadd
|
- groupadd
|
||||||
@@ -654,9 +209,9 @@ shadow-4.0.18.2 -> shadow-4.1.0 09-12-2007
|
|||||||
- Use MD5_CRYPT_ENAB, ENCRYPT_METHOD, SHA_CRYPT_MIN_ROUNDS, and
|
- Use MD5_CRYPT_ENAB, ENCRYPT_METHOD, SHA_CRYPT_MIN_ROUNDS, and
|
||||||
SHA_CRYPT_MAX_ROUNDS to define the default encryption algorithm for the
|
SHA_CRYPT_MAX_ROUNDS to define the default encryption algorithm for the
|
||||||
passwords.
|
passwords.
|
||||||
- chpasswd, chgpasswd, newusers: New options -c/--crypt-method and
|
- chpaswd, chgpasswd, newusers: New options -c/--crypt-method and
|
||||||
-s/--sha-rounds to supersede the system default encryption algorithm.
|
-s/--sha-rounds to supersede the system default encryption algorithm.
|
||||||
- chpasswd, chgpasswd, newusers: DES is no more the default algorithm. They
|
- chpaswd, chgpasswd, newusers: DES is no more the default algorithm. They
|
||||||
will respect the system default configured in /etc/login.defs
|
will respect the system default configured in /etc/login.defs
|
||||||
|
|
||||||
*** documentation:
|
*** documentation:
|
||||||
@@ -696,19 +251,19 @@ shadow-4.0.18 -> shadow-4.0.18.1 03-08-2006
|
|||||||
shadow-4.0.17 -> shadow-4.0.18 01-08-2006
|
shadow-4.0.17 -> shadow-4.0.18 01-08-2006
|
||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- su: fixed set environment too early when using PAM, so move it to !USE_PAM
|
- su: fixed set enviroment too early when using PAM, so move it to !USE_PAM
|
||||||
(patch submitted by Mike Frysinger <vapier@gentoo.org>),
|
(patch submitted by Mike Frysinger <vapier@gentoo.org>),
|
||||||
- groupadd, groupmod, useradd, usermod: fixed UID/GID overflow (fixed
|
- groupadd, groupmod, useradd, usermod: fixed UID/GID overflow (fixed
|
||||||
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=198920)
|
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=198920)
|
||||||
- passwd, useradd, usermod: fixed inactive/mindays/warndays/maxdays overflow
|
- passwd, useradd, usermod: fixed inactive/mindays/warndays/maxdays overflow
|
||||||
(similar to RH#198920),
|
(simillar to RH#198920),
|
||||||
- groupmems: rewritten for use PAM and getopt_long() and now it is enabled
|
- groupmems: rewrited for use PAM and getopt_long() and now it is enabled
|
||||||
for build and install (patch by George Kraft <gk4@swbell.net>),
|
for build and install (patch by George Kraft <gk4@swbell.net>),
|
||||||
- S/Key: removed assign getpass() to libshadow_getpass() on autoconf level
|
- S/Key: removed assign getpass() to libshadow_getpass() on autoconf level
|
||||||
(patch by Ulrich Mueller <ulm@kph.uni-mainz.de>; http://bugs.gentoo.org/139966),
|
(patch by Ulrich Mueller <ulm@kph.uni-mainz.de>; http://bugs.gentoo.org/139966),
|
||||||
- usermod: back to previous -a option semantics and clarify -a behavior
|
- usermod: back to previous -a option semantics and clarify -a behavior
|
||||||
on documentation level (by Greg Schafer <gschafer@zip.com.au>),
|
on documentation level (by Greg Schafer <gschafer@zip.com.au>),
|
||||||
- chsh, groupmod: rewritten for use getopt_long().
|
- chsh, groupmod: rewrited for use getopt_long().
|
||||||
- updated translations: ca, cs, da, eu, fr, gl, hu, ko, pl, pt, ru, sv, tr, uk, vi.
|
- updated translations: ca, cs, da, eu, fr, gl, hu, ko, pl, pt, ru, sv, tr, uk, vi.
|
||||||
*** documentation:
|
*** documentation:
|
||||||
- fr and ru man pages are up to date,
|
- fr and ru man pages are up to date,
|
||||||
@@ -743,7 +298,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
|
|||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- userdel: better fix for old CERT VU#312962 (which was fixed in shadow 4.0.8):
|
- userdel: better fix for old CERT VU#312962 (which was fixed in shadow 4.0.8):
|
||||||
fixed forgotten checking of the return value from fchown() before
|
fixed forgoten checking of the return value from fchown() before
|
||||||
proceeding with the fchmod() (based on Owl patch prepared by
|
proceeding with the fchmod() (based on Owl patch prepared by
|
||||||
Rafal Wojtczuk <nergal@owl.openwall.com>),
|
Rafal Wojtczuk <nergal@owl.openwall.com>),
|
||||||
- userdel: use login.defs::MAIL_DIR instead hardcoded /var/mail in created
|
- userdel: use login.defs::MAIL_DIR instead hardcoded /var/mail in created
|
||||||
@@ -755,7 +310,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
|
|||||||
passwords and libshadow_getpass() is used only because libc getpass()
|
passwords and libshadow_getpass() is used only because libc getpass()
|
||||||
do not handles password prompting with echo enabled,
|
do not handles password prompting with echo enabled,
|
||||||
- move login.defs::MD5_CRYPT_ENAB to non-PAM part,
|
- move login.defs::MD5_CRYPT_ENAB to non-PAM part,
|
||||||
- userdel: rewritten for use getopt_log(),
|
- userdel: rewrited for use getopt_log(),
|
||||||
- install default/template configuration files:
|
- install default/template configuration files:
|
||||||
-- if shadow is configured with use PAM install /etc/pam.d/* files,
|
-- if shadow is configured with use PAM install /etc/pam.d/* files,
|
||||||
-- if shadow do not uses PAM install /etc/{limits,login.acces} files,
|
-- if shadow do not uses PAM install /etc/{limits,login.acces} files,
|
||||||
@@ -793,7 +348,7 @@ shadow-4.0.15 -> shadow-4.0.16 05-06-2006
|
|||||||
- updated ru login.defs(5), passwd(1), userdel(8), usermod(8) man pages,
|
- updated ru login.defs(5), passwd(1), userdel(8), usermod(8) man pages,
|
||||||
- pw_auth(3) man page removed (outdated),
|
- pw_auth(3) man page removed (outdated),
|
||||||
- install limits(5), login.access(5) and porttime(5) man pages only when
|
- install limits(5), login.access(5) and porttime(5) man pages only when
|
||||||
shadow is built with PAM support disabled,
|
shadow is builded with PAM support disabled,
|
||||||
- passwd(1): better document how password strength is checked
|
- passwd(1): better document how password strength is checked
|
||||||
(fixed http://bugs.debian.org/115380),
|
(fixed http://bugs.debian.org/115380),
|
||||||
- usermod(8): added missing -a option description
|
- usermod(8): added missing -a option description
|
||||||
@@ -816,7 +371,7 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
|
|||||||
- login: default UMASK if not specified in login.defs is 022 (pointed by
|
- login: default UMASK if not specified in login.defs is 022 (pointed by
|
||||||
Peter Vrabec <pvrabec@redhat.com>),
|
Peter Vrabec <pvrabec@redhat.com>),
|
||||||
- chgpasswd: new tool (by Jonas Meurer <mejo@debian.org>),
|
- chgpasswd: new tool (by Jonas Meurer <mejo@debian.org>),
|
||||||
- lastlog: print the usage and exit if an additional argument is provided to
|
- lastlog: print the usage and exit if an additional argument is profided to
|
||||||
lastlog (merge 488_laslog_verify_arguments Debian patch),
|
lastlog (merge 488_laslog_verify_arguments Debian patch),
|
||||||
- login, newgrp, nologin, su: do not link with libselinux (merge
|
- login, newgrp, nologin, su: do not link with libselinux (merge
|
||||||
490_link_selinux_only_when_needed Debian patch),
|
490_link_selinux_only_when_needed Debian patch),
|
||||||
@@ -830,9 +385,9 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
|
|||||||
tries exceeded,
|
tries exceeded,
|
||||||
- always prints the number of tries in the syslog entry.
|
- always prints the number of tries in the syslog entry.
|
||||||
- add special handling for PAM_ABORT
|
- add special handling for PAM_ABORT
|
||||||
- add an entry to faillog, as when USE_PAM is not defined. (#53164)
|
- add an entry to failog, as when USE_PAM is not defined. (#53164)
|
||||||
- changed pam_end to PAM_END. This is certainly was a mistake. PAM_END is
|
- changed pam_end to PAM_END. This is certainly was a mistake. PAM_END is
|
||||||
pam_close_session + pam_end. Here, the session is still not open, we
|
pam_close_seesion + pam_end. Here, the session is still not open, we
|
||||||
don't have to close it.
|
don't have to close it.
|
||||||
- a HAVE_PAM_FAIL_DELAY is missing,
|
- a HAVE_PAM_FAIL_DELAY is missing,
|
||||||
- su: fixed pam session support (patch from Topi Miettinen; fixed #57526,
|
- su: fixed pam session support (patch from Topi Miettinen; fixed #57526,
|
||||||
@@ -840,7 +395,7 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
|
|||||||
- userdel: user's group is already removed by update_groups().
|
- userdel: user's group is already removed by update_groups().
|
||||||
remove_group() is not needed (bug introduced in 4.0.14 on merge FC fixes).
|
remove_group() is not needed (bug introduced in 4.0.14 on merge FC fixes).
|
||||||
Fixed by Nicolas François <nicolas.francois@centraliens.net>,
|
Fixed by Nicolas François <nicolas.francois@centraliens.net>,
|
||||||
- useradd: always remove group and gshadow databases lock, Fixed by Nicolas
|
- useradd: allways remove group and gshadow databases lock, Fixed by Nicolas
|
||||||
François <nicolas.francois@centraliens.net>
|
François <nicolas.francois@centraliens.net>
|
||||||
(http://bugs.debian.org/348250)
|
(http://bugs.debian.org/348250)
|
||||||
- auditing fixes:
|
- auditing fixes:
|
||||||
@@ -848,14 +403,14 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
|
|||||||
added audit_logger() prototype),
|
added audit_logger() prototype),
|
||||||
- useradd: fixed excess audit_logger() argument,
|
- useradd: fixed excess audit_logger() argument,
|
||||||
- chage: added missing \n on display password status if password must be
|
- chage: added missing \n on display password status if password must be
|
||||||
changed,
|
chaged,
|
||||||
- useradd: fixed allow non-unique UID (http://bugs.debian.org/351281),
|
- useradd: fixed allow non-unique UID (http://bugs.debian.org/351281),
|
||||||
- various code cleanups for make possible compilation of shadow with -Wall
|
- variouse code cleanups for make possible compilation of shadow with -Wall
|
||||||
-Werror (by Alexander Gattin <xrgtn@yandex.ru>),
|
-Werror (by Alexander Gattin <xrgtn@yandex.ru>),
|
||||||
- su: move exit() outside libmisc/shell.c::shell() for handle shell() errors
|
- su: move exit() outside libmisc/shell.c::shell() for handle shell() errors
|
||||||
on higher level (now is better visable where some programs exit with 126
|
on higher level (now is better visable where some programs exit with 126
|
||||||
and 127 exit codes); added new shell() parameter (char *const envp[])
|
and 127 exit codes); added new shell() parameter (char *const envp[])
|
||||||
which allow fix preserving environment in su on using -p, (patch by
|
which allow fix preserving enviloment in su on using -p, (patch by
|
||||||
Alexander Gattin <xrgtn@yandex.ru>),
|
Alexander Gattin <xrgtn@yandex.ru>),
|
||||||
- su: added handle -c,--command option for GNU su compliance (merge
|
- su: added handle -c,--command option for GNU su compliance (merge
|
||||||
437_su_-c_option Debian patch),
|
437_su_-c_option Debian patch),
|
||||||
@@ -903,7 +458,7 @@ shadow-4.0.13 -> shadow-4.0.14 03-01-2006
|
|||||||
- userdel: make the -f option force the removal of the user's group (even if it
|
- userdel: make the -f option force the removal of the user's group (even if it
|
||||||
is the primary group of another user)
|
is the primary group of another user)
|
||||||
(merge 453_userdel_-f_removes_group Debian patch),
|
(merge 453_userdel_-f_removes_group Debian patch),
|
||||||
- usermod: rewritten for use getopt_long() (Christian Perrier <bubulle@kheops.frmug.org>),
|
- usermod: rewrited for use getopt_long() (Christian Perrier <bubulle@kheops.frmug.org>),
|
||||||
- grpck: fixed segmentation fault on using -s when /etc/gshadow is empty (fix by
|
- grpck: fixed segmentation fault on using -s when /etc/gshadow is empty (fix by
|
||||||
Tomasz Lemiech <szpajder@staszic.waw.pl>),
|
Tomasz Lemiech <szpajder@staszic.waw.pl>),
|
||||||
- passwd: remove handle -f, -g and -s options.
|
- passwd: remove handle -f, -g and -s options.
|
||||||
@@ -912,7 +467,7 @@ shadow-4.0.13 -> shadow-4.0.14 03-01-2006
|
|||||||
Nicolas François <nicolas.francois@centraliens.net>)
|
Nicolas François <nicolas.francois@centraliens.net>)
|
||||||
- su: export $USER and $SHELL as well as $HOME (http://bugs.debian.org/11003 and
|
- su: export $USER and $SHELL as well as $HOME (http://bugs.debian.org/11003 and
|
||||||
http://bugs.debian.org/11189),
|
http://bugs.debian.org/11189),
|
||||||
- su, vipw: rewritten for use getopt_long(),
|
- su, vipw: rewrited for use getopt_long(),
|
||||||
- su: log successful/failed through syslog (http://bugs.debian.org/190215),
|
- su: log successful/failed through syslog (http://bugs.debian.org/190215),
|
||||||
- updated translations: ca, cs, da, eu, fi, fr, it, pl, pt, ru, sv, tl, vi,
|
- updated translations: ca, cs, da, eu, fi, fr, it, pl, pt, ru, sv, tl, vi,
|
||||||
- new translations: gl.
|
- new translations: gl.
|
||||||
@@ -946,7 +501,7 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
|
|||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- chage: removed duplicated pam_start(),
|
- chage: removed duplicated pam_start(),
|
||||||
- chfn, chsh: finished PAM support using pam_start() and co.,
|
- chfn, chsh: finished PAM support usin pam_start() and co.,
|
||||||
- userdel: userdel should not remove the group which is primary for someone else
|
- userdel: userdel should not remove the group which is primary for someone else
|
||||||
(fix by Nicolas François <nicolas.francois@centraliens.net>
|
(fix by Nicolas François <nicolas.francois@centraliens.net>
|
||||||
http://bugs.debian.org/295416),
|
http://bugs.debian.org/295416),
|
||||||
@@ -955,7 +510,7 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
|
|||||||
- fixedlib/commonio.c: don't assume selinux is enabled if is_selinux_enabled()
|
- fixedlib/commonio.c: don't assume selinux is enabled if is_selinux_enabled()
|
||||||
returns -1 (merge isSelinuxEnabled FC patch by Jeremy Katz <katzj@redhat.com>),
|
returns -1 (merge isSelinuxEnabled FC patch by Jeremy Katz <katzj@redhat.com>),
|
||||||
- login, su (non-PAM case): fixed setup max address space limits (added missing break
|
- login, su (non-PAM case): fixed setup max address space limits (added missing break
|
||||||
statement in case) spotted by Lasse Collin <lasse.collin@tukaani.org>,
|
statement in case) spoted by Lasse Collin <lasse.collin@tukaani.org>,
|
||||||
- auditing support added. Patch prepared by Peter Vrabec <pvrabec@redhat.com> basing
|
- auditing support added. Patch prepared by Peter Vrabec <pvrabec@redhat.com> basing
|
||||||
on work by Steve Grubb from http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=159215
|
on work by Steve Grubb from http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=159215
|
||||||
Now auditing support have commands: chage, gpasswd, groupadd, groupdel, groupmod,
|
Now auditing support have commands: chage, gpasswd, groupadd, groupdel, groupmod,
|
||||||
@@ -966,18 +521,18 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
|
|||||||
to example described in ident(1) man page (modern compilers like latest GCC
|
to example described in ident(1) man page (modern compilers like latest GCC
|
||||||
removes not used functions by global optimization).
|
removes not used functions by global optimization).
|
||||||
So "ident /usr/bin/passwd" will show again some useable informations
|
So "ident /usr/bin/passwd" will show again some useable informations
|
||||||
- su: fixed twice copy environment which causes auth problems
|
- su: fixed twice copy enviroment which causes auth problems
|
||||||
(bug was introduced in 4.0.12; fix by Nicolas François <nicolas.francois@centraliens.net>),
|
(bug was introduced in 4.0.12; fix by Nicolas François <nicolas.francois@centraliens.net>),
|
||||||
- chage: differentiate the different failure causes by the exit value
|
- chage: differentiate the different failure causes by the exit value
|
||||||
This will permit to adduser Debian script to detect if chage failed because the
|
This will permit to adduser Debian script to detect if chage failed because the
|
||||||
system doesn't have shadowed passwords (fix for http://bugs.debian.org/317012),
|
system doesn't have shadowed passwords (fix for http://bugs.debian.org/317012),
|
||||||
- merge 010_more-i18ned-messages Debian patch which adds i18n support for few
|
- merge 010_more-i18ned-messages Debian patch which adds i18n support for few
|
||||||
more messages (originally patch was prepared by Guillem Jover <guillem@debian.org>),
|
more messages (orginaly patch was prepared by Guillem Jover <guillem@debian.org>),
|
||||||
- lastlog: added handle -b option which allow print only lastlog records older than
|
- lastlog: added handle -b option which allow print only lastlog records older than
|
||||||
specified DAYS (fix by <miles@lubin.us>),
|
specified DAYS (fix by <miles@lubin.us>),
|
||||||
- chpasswd, gpasswd, newusers: fixed libmisc/salt.c for use login.defs::MD5_CRYPT_ENAB
|
- chpasswd, gpasswd, newusers: fixed libmisc/salt.c for use login.defs::MD5_CRYPT_ENAB
|
||||||
only if PAM support is disabled (fix by John Gatewood Ham <zappaman@buraphalinux.org>),
|
only if PAM support is disabled (fix by John Gatewood Ham <zappaman@buraphalinux.org>),
|
||||||
- passwd: rewritten for use getopt_long(),
|
- passwd: rewrited for use getopt_long(),
|
||||||
- newgrp: when newgrp process sits between parent and child shells, it should
|
- newgrp: when newgrp process sits between parent and child shells, it should
|
||||||
propagate STOPs from child to parent and CONTs from parent to child,
|
propagate STOPs from child to parent and CONTs from parent to child,
|
||||||
otherwise e.g. bash's "suspend" command won't work
|
otherwise e.g. bash's "suspend" command won't work
|
||||||
@@ -987,11 +542,11 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
|
|||||||
- chsh(1), groupadd(8), newusers(8), pwconv(8), useradd(8), userdel(8), usermod(8):
|
- chsh(1), groupadd(8), newusers(8), pwconv(8), useradd(8), userdel(8), usermod(8):
|
||||||
added missing references to /etc/login.defs and login.defs(5)
|
added missing references to /etc/login.defs and login.defs(5)
|
||||||
(Christian Perrier <bubulle@kheops.frmug.org>),
|
(Christian Perrier <bubulle@kheops.frmug.org>),
|
||||||
- passwd(5): rewritten based on work by Greg Wooledge <greg@wooledge.org>
|
- passwd(5): rewrited based on work by Greg Wooledge <greg@wooledge.org>
|
||||||
http://bugs.debian.org/328113
|
http://bugs.debian.org/328113
|
||||||
- login(1): added securetty(5) to SEE ALSO section
|
- login(1): added securetty(5) to SEE ALSO section
|
||||||
(fixed Debian bug http://bugs.debian.org/325773),
|
(fixed Debian bug http://bugs.debian.org/325773),
|
||||||
- groupadd(8), useradd(8): fix regular expression describing allowed login/group
|
- groupadd(8), useradd(8): fix regular expression describing alloved login/group
|
||||||
names (pointed by Nicolas François <nicolas.francois@centraliens.net>)
|
names (pointed by Nicolas François <nicolas.francois@centraliens.net>)
|
||||||
(correct is [a-z_][a-z0-9_-]*[$]),
|
(correct is [a-z_][a-z0-9_-]*[$]),
|
||||||
- groupadd(8), useradd(8): documents in CAVEATS section the limitations shadow
|
- groupadd(8), useradd(8): documents in CAVEATS section the limitations shadow
|
||||||
@@ -1001,9 +556,9 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
|
|||||||
shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005
|
shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005
|
||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- newgrp, login: remove using login.defs::CLOSE_SESSIONS variable and always
|
- newgrp, login: remove using login.defs::CLOSE_SESSIONS variable and allways
|
||||||
close PAM session,
|
close PAM session,
|
||||||
- fixed configure.in: really enable shadow group support by default (pointed by
|
- fixed configure.in: realy enable shadow group support by default (pointed by
|
||||||
Greg Schafer <gschafer@zip.com.au> and Peter Vrabec <pvrabec@redhat.com>),
|
Greg Schafer <gschafer@zip.com.au> and Peter Vrabec <pvrabec@redhat.com>),
|
||||||
- login.defs: removed handle QMAIL_DIR variable,
|
- login.defs: removed handle QMAIL_DIR variable,
|
||||||
- login: allow regular user to login on read-only root file system (not only for root)
|
- login: allow regular user to login on read-only root file system (not only for root)
|
||||||
@@ -1028,9 +583,9 @@ shadow-4.0.11.1 -> shadow-4.0.12 22-08-2005
|
|||||||
period and permit brute-force attacks (fixed http://bugs.debian.org/288827),
|
period and permit brute-force attacks (fixed http://bugs.debian.org/288827),
|
||||||
- uClibc fixes (by Martin Schlemmer <azarah@nosferatu.za.org>):
|
- uClibc fixes (by Martin Schlemmer <azarah@nosferatu.za.org>):
|
||||||
added require ngettext (added [need-ngettext] to AM_GNU_GETTEXT() parameters)
|
added require ngettext (added [need-ngettext] to AM_GNU_GETTEXT() parameters)
|
||||||
and stub prototype for ngettext() in lib/prototypes.h (necessary if shadow
|
and stub prototype for ngettext() in lib/prototypes.h (neccessary if shadow
|
||||||
compiled with disabled NLS support)
|
compiled with disabled NLS support)
|
||||||
- groupadd: rewritten for use getopt_long(),
|
- groupadd: rewrited for use getopt_long(),
|
||||||
- groupadd, groupdel, groupmod, userdel: do OPENLOG() before pam_start(),
|
- groupadd, groupdel, groupmod, userdel: do OPENLOG() before pam_start(),
|
||||||
- groupadd: fixed double OPENLOG(),
|
- groupadd: fixed double OPENLOG(),
|
||||||
- removed lib/{grpack,gspack,pwpack,sppack}.c and prototypes from lib/prototypes.h
|
- removed lib/{grpack,gspack,pwpack,sppack}.c and prototypes from lib/prototypes.h
|
||||||
@@ -1066,7 +621,7 @@ shadow-4.0.10 -> shadow-4.0.11 18-07-2005
|
|||||||
- su: ignore SIGINT while authenticating. A ^C could defeat the waiting period and
|
- su: ignore SIGINT while authenticating. A ^C could defeat the waiting period and
|
||||||
permit brute-force attacks. Also ignore SIGQUIT.
|
permit brute-force attacks. Also ignore SIGQUIT.
|
||||||
Fixed: http://bugs.debian.org/52372 and http://bugs.debian.org/288827
|
Fixed: http://bugs.debian.org/52372 and http://bugs.debian.org/288827
|
||||||
- useradd: rewritten for use getopt_long(),
|
- useradd: rewrited for use getopt_long(),
|
||||||
- newgrp: add fix for handle splitted NIS groups: extends the functionality that,
|
- newgrp: add fix for handle splitted NIS groups: extends the functionality that,
|
||||||
if the requested group is given, all groups of the same GID are tested for
|
if the requested group is given, all groups of the same GID are tested for
|
||||||
membership of the requesting user.
|
membership of the requesting user.
|
||||||
@@ -1097,7 +652,7 @@ shadow-4.0.10 -> shadow-4.0.11 18-07-2005
|
|||||||
- updated translations: cs, da, de, es, fi, pl, pt, ro, ru, sk.
|
- updated translations: cs, da, de, es, fi, pl, pt, ro, ru, sk.
|
||||||
*** documentation:
|
*** documentation:
|
||||||
- pwck(8): document -q option (based on Debian patch for fix http://bugs.debian.org/309408)
|
- pwck(8): document -q option (based on Debian patch for fix http://bugs.debian.org/309408)
|
||||||
- pwck(8): rewritten OPTIONS section and better SYNOPSIS,
|
- pwck(8): rewrited OPTIONS section and better SYNOPSIS,
|
||||||
- lastlog(8): document that lastlog is a sparse file, and don't need to be rotated
|
- lastlog(8): document that lastlog is a sparse file, and don't need to be rotated
|
||||||
http://bugs.debian.org/219321
|
http://bugs.debian.org/219321
|
||||||
- login(8): better explain the respective roles of login, init and getty with regards
|
- login(8): better explain the respective roles of login, init and getty with regards
|
||||||
@@ -1111,12 +666,12 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
|
|||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- mkpasswd: removed,
|
- mkpasswd: removed,
|
||||||
- userdel: now deletes user groups from /etc/gshadow as well as /etc/group.
|
- userdel: now deletes user groups from /etc/gshdow as well as /etc/group.
|
||||||
Fix by Nicolas François <nicolas.francois@centraliens.net>.
|
Fix by Nicolas François <nicolas.francois@centraliens.net>.
|
||||||
http://bugs.debian.org/99442
|
http://bugs.debian.org/99442
|
||||||
- usermod: when relocating a user's home directory, don't fail and remove the new
|
- usermod: when relocating a user's home directory, don't fail and remove the new
|
||||||
home directory if we can't remove the old home directory for some
|
home directory if we can't remove the old home directory for some
|
||||||
reason; the results can be spectacularly poor if, for instance, only
|
reason; the results can be spectularly poort if, for instance, only
|
||||||
the rmdir() fails. Patch prepared by Timo Lindfors <lindi-spamtrap@newmail.com>.
|
the rmdir() fails. Patch prepared by Timo Lindfors <lindi-spamtrap@newmail.com>.
|
||||||
http://bugs.debian.org/166369
|
http://bugs.debian.org/166369
|
||||||
- su: fix syslogs to be less ambiguous. Use old:new format instead of old-new
|
- su: fix syslogs to be less ambiguous. Use old:new format instead of old-new
|
||||||
@@ -1124,7 +679,7 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
|
|||||||
http://bugs.debian.org/213592
|
http://bugs.debian.org/213592
|
||||||
- removed not used now libmisc/setup.c,
|
- removed not used now libmisc/setup.c,
|
||||||
- login: use also UTMPX API instead UTMP on failure (login was affected for this
|
- login: use also UTMPX API instead UTMP on failure (login was affected for this
|
||||||
when shadow was built without PAM support)
|
when shadow was builded without PAM support)
|
||||||
patch by Nicolas François <nicolas.francois@centraliens.net>
|
patch by Nicolas François <nicolas.francois@centraliens.net>
|
||||||
- login: the PAM session needs to be closed as root, thus before change_uid()
|
- login: the PAM session needs to be closed as root, thus before change_uid()
|
||||||
http://bugs.debian.org/53570 http://bugs.debian.org/195048 http://bugs.debian.org/211884
|
http://bugs.debian.org/53570 http://bugs.debian.org/195048 http://bugs.debian.org/211884
|
||||||
@@ -1133,14 +688,14 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
|
|||||||
http://bugs.debian.org/53702
|
http://bugs.debian.org/53702
|
||||||
- login: check for hushed login and pass PAM_SILENT if true,
|
- login: check for hushed login and pass PAM_SILENT if true,
|
||||||
http://bugs.debian.org/48002
|
http://bugs.debian.org/48002
|
||||||
- login: fixed username on successful login (was using the normal username,
|
- login: fixed username on succesful login (was using the normal username,
|
||||||
when it should have used pam_user) http://bugs.debian.org/47819
|
when it should have used pam_user) http://bugs.debian.org/47819
|
||||||
- remove using SHADOWPWD #define so now shadow is always built with shadow
|
- remove using SHADOWPWD #define so now shadow is allways builded with shadow
|
||||||
password support,
|
passwowd support,
|
||||||
- chage: rewritten for use getopt_long(),
|
- chage: rewrited for use getopt_long(),
|
||||||
- updated translations: ca, cs, da, fi, pl, ru, zh_TW.
|
- updated translations: ca, cs, da, fi, pl, ru, zh_TW.
|
||||||
*** documentation:
|
*** documentation:
|
||||||
- most of the man pages now are generated from XML files so in case submitting any
|
- most of the man pages now are generated from XML files so in case submiting any
|
||||||
chages to this resources please make diff to XML files,
|
chages to this resources please make diff to XML files,
|
||||||
- chfn: give more details about the influence of login.defs on what's allowed to
|
- chfn: give more details about the influence of login.defs on what's allowed to
|
||||||
users.
|
users.
|
||||||
@@ -1148,7 +703,7 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
|
|||||||
shadow-4.0.8 -> shadow-4.0.9 23-05-2005
|
shadow-4.0.8 -> shadow-4.0.9 23-05-2005
|
||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- passwd: fixed segfault in non-PAM configuration
|
- passwd: fixed segfault in non-PAM connfiguration
|
||||||
(submited by Greg Schafer <gschafer@zip.com.au>),
|
(submited by Greg Schafer <gschafer@zip.com.au>),
|
||||||
- newgrp: fixed NULL pointer dereference - getlogin() and ttyname() can
|
- newgrp: fixed NULL pointer dereference - getlogin() and ttyname() can
|
||||||
return NULL which is not checked (http://bugs.debian.org/162303),
|
return NULL which is not checked (http://bugs.debian.org/162303),
|
||||||
@@ -1170,15 +725,15 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
|
|||||||
- configure.in: add using AC_GNU_SOURCE macro for kill compilation warnings about
|
- configure.in: add using AC_GNU_SOURCE macro for kill compilation warnings about
|
||||||
implicit declaration of function `fseeko',
|
implicit declaration of function `fseeko',
|
||||||
- faillog: changed faillog record display format for allow fit in 80 columns all
|
- faillog: changed faillog record display format for allow fit in 80 columns all
|
||||||
faillog attributes,
|
faillog atributies,
|
||||||
- removed NDBM code (unused),
|
- removed NDBM code (unused),
|
||||||
- fixed use of SU_WHEEL_ONLY in su. Now su really is available for wheel group
|
- fixed use of SU_WHEEL_ONLY in su. Now su realy is avalaible for wheel group
|
||||||
members. Thanks to Mike Frysinger <vapier@gentoo.org> for report:
|
members. Thanks to Mike Frysinger <vapier@gentoo.org> for report:
|
||||||
http://bugs.gentoo.org/show_bug.cgi?id=80345
|
http://bugs.gentoo.org/show_bug.cgi?id=80345
|
||||||
- drop never finished kerberos and des_rpc support (for kerberos support back firs
|
- drop never finished kerberos and des_rpc support (for kerberos support back firs
|
||||||
must be prepared modularization),
|
must be prepared modularization),
|
||||||
- fixed UTMP path detection (by Kelledin <kelledin@users.sf.net>),
|
- fixed UTMP path detection (by Kelledin <kelledin@users.sf.net>),
|
||||||
- useradd: rewritten group count to dynamic (by John Newbigin
|
- useradd: rewrited group count to dynamic (by John Newbigin
|
||||||
<jnewbigin@ict.swin.edu.au>),
|
<jnewbigin@ict.swin.edu.au>),
|
||||||
- login: fixed create lastlog entry fo users never loged in on non-PAM
|
- login: fixed create lastlog entry fo users never loged in on non-PAM
|
||||||
variant of login (fix by <oracular@ziplip.com>),
|
variant of login (fix by <oracular@ziplip.com>),
|
||||||
@@ -1193,7 +748,7 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
|
|||||||
fchmod() is executed. (Actually, we could also pass the final "mode" to
|
fchmod() is executed. (Actually, we could also pass the final "mode" to
|
||||||
the open() call and then save the consequent fchmod().)
|
the open() call and then save the consequent fchmod().)
|
||||||
- SELinux changes: added changes in chage, chfn, chsh, passwd for allow
|
- SELinux changes: added changes in chage, chfn, chsh, passwd for allow
|
||||||
construct more grained user password/account properties on SELinux
|
construct more grained user password/accuunt properties on SELinux
|
||||||
policies level. Patch originally based on RH changes (submited by Chris
|
policies level. Patch originally based on RH changes (submited by Chris
|
||||||
PeBenito <pebenito@gentoo.org>),
|
PeBenito <pebenito@gentoo.org>),
|
||||||
- added SELinux changes: in libmisc/copydir.c (based on Fedora patch),
|
- added SELinux changes: in libmisc/copydir.c (based on Fedora patch),
|
||||||
@@ -1211,8 +766,8 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
|
|||||||
- newgrp(1): fix #251926, #166173, #113191 Debian bugs: explain why editing /etc/group
|
- newgrp(1): fix #251926, #166173, #113191 Debian bugs: explain why editing /etc/group
|
||||||
(without gshadow) doesn't permit to use newgrp,
|
(without gshadow) doesn't permit to use newgrp,
|
||||||
- newgrp(1): newgrp uses /bin/sh (not bash),
|
- newgrp(1): newgrp uses /bin/sh (not bash),
|
||||||
- faillog(8): updated after rewritten faillog command for use getopt_long(),
|
- faillog(8): updated after rewrited faillog command for use getopt_long(),
|
||||||
- login(1): removed fragment about abilities pass environment variables in login prompt,
|
- login(1): removed fragment about abilities pass enviroment variables in login prompt,
|
||||||
- gshadow(5): new file (by Nicolas Nicolas François <nicolas.francois@centraliens.net>),
|
- gshadow(5): new file (by Nicolas Nicolas François <nicolas.francois@centraliens.net>),
|
||||||
- usermod(8): fixed #302388 Debian bug: added separated -o option description,
|
- usermod(8): fixed #302388 Debian bug: added separated -o option description,
|
||||||
|
|
||||||
@@ -1229,24 +784,24 @@ shadow-4.0.6 -> shadow-4.0.7 26-01-2005
|
|||||||
-- use fseeko() instead fseek() and remove casting file offsets to unsigned
|
-- use fseeko() instead fseek() and remove casting file offsets to unsigned
|
||||||
long.
|
long.
|
||||||
- lastlog:
|
- lastlog:
|
||||||
-- rewritten source code using the same style as in chpasswd.c,
|
-- rewrited source code using the same style as in chpasswd.c,
|
||||||
-- open lastlog file after finish parse commandline options
|
-- open lastlog file after finish parse comman line optiomns
|
||||||
(now --help output can be displayed for users without lastlog
|
(now --help otput can be displayd for users without lastlog
|
||||||
file read permission),
|
file read permission),
|
||||||
-- cleanups in lastlog(8) man page using the same style as in
|
-- cleanups in lastlog(8) man page using the same style as in
|
||||||
chpasswd(8).
|
chpasswd(8).
|
||||||
- chpasswd:
|
- chpasswd:
|
||||||
-- switch chpasswd to use getopt_long() and adds a --md5 option
|
-- switch chpasswd to use getopt_long() and adds a --md5 option
|
||||||
(by Ian Gulliver <ian@penguinhosting.net>),
|
(by Ian Gulliver <ian@penguinhosting.net>),
|
||||||
-- rewritten chpasswd(8) man page.
|
-- rewrited chpasswd(8) man page.
|
||||||
|
|
||||||
shadow-4.0.5 -> shadow-4.0.6 08-11-2004
|
shadow-4.0.5 -> shadow-4.0.6 08-11-2004
|
||||||
|
|
||||||
- su: fixed adding of pam_env env variables to environment
|
- su: fixed adding of pam_env env variables to enviroment
|
||||||
(Martin Schlemmer <azarah@nosferatu.za.org>),
|
(Martin Schlemmer <azarah@nosferatu.za.org>),
|
||||||
- autoconf: fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables
|
- autoconf: fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables
|
||||||
which was always empty (Gregorio Guidi <g.guidi@sns.it>),
|
which was allways empty (Gregorio Guidi <g.guidi@sns.it>),
|
||||||
- really close security bug in libmisc/pwdcheck.c,
|
- realuy closse security bug in libmisc/pwdcheck.c,
|
||||||
- added missing template/example PAM service config files for chfn, chsh and
|
- added missing template/example PAM service config files for chfn, chsh and
|
||||||
userdel,
|
userdel,
|
||||||
- do not translate variable names from /etc/default/useradd during
|
- do not translate variable names from /etc/default/useradd during
|
||||||
@@ -1257,10 +812,10 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
|
|||||||
- change libmisc to private static library,
|
- change libmisc to private static library,
|
||||||
- added SELinux support (basing on patch from Gentoo),
|
- added SELinux support (basing on patch from Gentoo),
|
||||||
- chage: more verbose/human readable -l output. This output is much more
|
- chage: more verbose/human readable -l output. This output is much more
|
||||||
better for send directly via email for each users as message with account
|
beter for send directly via email for each users as message with account
|
||||||
status (for example as message with warning about account/password expiration),
|
status (for example as message with warning about account/password expiration),
|
||||||
- login: fixed handle -f option: now it works correctly without specify "-h
|
- login: fixed handle -f option: now it works correctly without specify "-h
|
||||||
<host>" if open login session locally is required (thanks for help
|
<host>" if open login session localy is required (thanks for help
|
||||||
investigate bug for Krzysztof Kotlenga),
|
investigate bug for Krzysztof Kotlenga),
|
||||||
- userdel: when removing a user with userdel, userdel was always exits with 1 (fixed).
|
- userdel: when removing a user with userdel, userdel was always exits with 1 (fixed).
|
||||||
Based on http://bugs.gentoo.org/show_bug.cgi?id=66687,
|
Based on http://bugs.gentoo.org/show_bug.cgi?id=66687,
|
||||||
@@ -1274,8 +829,8 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
|
|||||||
makes httpd Option SymlinkIfOwnerMatch break for default weg pages
|
makes httpd Option SymlinkIfOwnerMatch break for default weg pages
|
||||||
including symlinks placed into /etc/skel/public_html for example.
|
including symlinks placed into /etc/skel/public_html for example.
|
||||||
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=66819
|
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=66819
|
||||||
- su: add pam_open_session() support. If built without PAM support
|
- su: add pam_open_session() support. If builded without PAM support
|
||||||
propagate $DISPLAY and $XAUTHORITY environment variables.
|
propagate $DISPLAY and $XAUTHORITY enviroment variables.
|
||||||
Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1
|
Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1
|
||||||
- applied 036_pam_access_with_preauth.patch Debian patch submited by Bjorn
|
- applied 036_pam_access_with_preauth.patch Debian patch submited by Bjorn
|
||||||
Torkelsson <Bjorn.Torkelsson@hpc2n.umu.se>: add support for PAM account
|
Torkelsson <Bjorn.Torkelsson@hpc2n.umu.se>: add support for PAM account
|
||||||
@@ -1287,11 +842,11 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
|
|||||||
Use constant strings rather than argv[0] for syslog ident in the user
|
Use constant strings rather than argv[0] for syslog ident in the user
|
||||||
management commands,
|
management commands,
|
||||||
shadow-4.0.4.1-owl-tmp.diff:
|
shadow-4.0.4.1-owl-tmp.diff:
|
||||||
Remove using mktemp() if mkstemp() prototype not found (use always mkstemp()),
|
Remove using mktemp() if mkstemp() prototype not found (use allways mkstemp()),
|
||||||
shadow-4.0.4.1-owl-check-reads.diff:
|
shadow-4.0.4.1-owl-check-reads.diff:
|
||||||
Add checking for read errors in commonio and vipw/vigr (not doing so could
|
Add checking for read errors in commonio and vipw/vigr (not doing so could
|
||||||
result in data loss when the records are written back),
|
result in data loss when the records are written back),
|
||||||
- fixed security bug in libmisc/pwdcheck.c which allow unauthorized
|
- fixed securirty bug in libmisc/pwdcheck.c which allow unauthorized
|
||||||
account properties modification.
|
account properties modification.
|
||||||
Affected tools: chfn and chsh.
|
Affected tools: chfn and chsh.
|
||||||
Bug was discovered by Martin Schulze <joey@infodrom.org>.
|
Bug was discovered by Martin Schulze <joey@infodrom.org>.
|
||||||
@@ -1307,12 +862,12 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
|
|||||||
|
|
||||||
shadow-4.0.4 => shadow-4.0.4.1 14-01-2004
|
shadow-4.0.4 => shadow-4.0.4.1 14-01-2004
|
||||||
- bug fixes in automake files for generate correct tar ball on "make dist":
|
- bug fixes in automake files for generate correct tar ball on "make dist":
|
||||||
added missing "EXTRA_DIST = $(man_MANS)" in man/*/Makefile.am.
|
added mising "EXTRA_DIST = $(man_MANS)" in man/*/Makefile.am.
|
||||||
|
|
||||||
shadow-4.0.3 => shadow-4.0.4 14-01-2004
|
shadow-4.0.3 => shadow-4.0.4 14-01-2004
|
||||||
|
|
||||||
*** general:
|
*** general:
|
||||||
- added missing information about -f options in groupadd usage message
|
- added missing information about -f options in groupadd usage mesage
|
||||||
(document this also in man page),
|
(document this also in man page),
|
||||||
- removed TCFS support (tcfs is dead),
|
- removed TCFS support (tcfs is dead),
|
||||||
- convert all po/*.po files to utf-8,
|
- convert all po/*.po files to utf-8,
|
||||||
@@ -1320,7 +875,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
|
|||||||
per service flushing method instead HUPing nscd process),
|
per service flushing method instead HUPing nscd process),
|
||||||
- removed old AUTH_METHODS dependent code,
|
- removed old AUTH_METHODS dependent code,
|
||||||
- chage: now all code depend on SHADOWPWD. If shadow will not be configured
|
- chage: now all code depend on SHADOWPWD. If shadow will not be configured
|
||||||
on autoconf level for using shadow password chage is olny stub which
|
on autoconf level for using shadow possword chage is olny stub which
|
||||||
informs "chage not configured for shadow password support."
|
informs "chage not configured for shadow password support."
|
||||||
- dpasswd: removed,
|
- dpasswd: removed,
|
||||||
- login: remove handle login.defs::DIALUPS_CHECK_ENAB code,
|
- login: remove handle login.defs::DIALUPS_CHECK_ENAB code,
|
||||||
@@ -1328,7 +883,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
|
|||||||
- ALL tools, libraries: remove old SVR4, SVR4_SI86_EUA BSD_QUOTA and ATT_AGE
|
- ALL tools, libraries: remove old SVR4, SVR4_SI86_EUA BSD_QUOTA and ATT_AGE
|
||||||
dependent code,
|
dependent code,
|
||||||
- ALL: ready for gettext 0.11.5, automake 1.7.4, autoconf 2.57,
|
- ALL: ready for gettext 0.11.5, automake 1.7.4, autoconf 2.57,
|
||||||
- logoutd, userd: handle also utmpx if available,
|
- logoutd, userd: handle also utmpx if avalaile,
|
||||||
- newgrp: fix for non-PAM version
|
- newgrp: fix for non-PAM version
|
||||||
Use CLOSE_SESSIONS depending code only when USE_PAM.
|
Use CLOSE_SESSIONS depending code only when USE_PAM.
|
||||||
The problem was reported by Mattias Webjorn Eriksson using Slackware
|
The problem was reported by Mattias Webjorn Eriksson using Slackware
|
||||||
@@ -1356,7 +911,7 @@ shadow-4.0.3 => shadow-4.0.4 14-01-2004
|
|||||||
|
|
||||||
shadow-4.0.2 => shadow-4.0.3 13-03-2002
|
shadow-4.0.2 => shadow-4.0.3 13-03-2002
|
||||||
|
|
||||||
- added various cs, de, fr, id, it, ko man pages found mainly in national
|
- added variouse cs, de, fr, id, it, ko man pages found mainly in national
|
||||||
man pages translations projects (this documents are not synced with
|
man pages translations projects (this documents are not synced with
|
||||||
current en version but you know .. "Documentations is lik sex. When it is
|
current en version but you know .. "Documentations is lik sex. When it is
|
||||||
good it very very good. Whet it is bad it is better than nothing."). Any
|
good it very very good. Whet it is bad it is better than nothing."). Any
|
||||||
@@ -1372,9 +927,9 @@ shadow-4.0.2 => shadow-4.0.3 13-03-2002
|
|||||||
shadow-4.0.1 => shadow-4.0.2 17-02-2002
|
shadow-4.0.1 => shadow-4.0.2 17-02-2002
|
||||||
|
|
||||||
- resolve many fuzzy translations also all this which may cause problems on
|
- resolve many fuzzy translations also all this which may cause problems on
|
||||||
displaying long uid/gid,
|
displaing long uid/gid,
|
||||||
- allow use "$" on ending in created by useradd username accounts for allow
|
- allow use "$" on ending in cereated by useradd usermname accounts for allow
|
||||||
create machine accounts for samba (thanks to Jerome Borsboom
|
create machine acounts for samba (thanks to Jerome Borsboom
|
||||||
<borsboom@tch.fgg.eur.nl> for point this problem in 4.0.1),
|
<borsboom@tch.fgg.eur.nl> for point this problem in 4.0.1),
|
||||||
- fix small but ugly bug in configure.in in libpam_mics library detection.
|
- fix small but ugly bug in configure.in in libpam_mics library detection.
|
||||||
|
|
||||||
@@ -1394,7 +949,7 @@ shadow-4.0.0 => shadow-4.0.1
|
|||||||
as root. If root does read-only, there's no lock needed. Added missing
|
as root. If root does read-only, there's no lock needed. Added missing
|
||||||
"#include <errno.h>" for above (me).
|
"#include <errno.h>" for above (me).
|
||||||
shadow-4.0.0-owl-warnings.diff
|
shadow-4.0.0-owl-warnings.diff
|
||||||
Olny one fix from this patch was applied because other was fixed few days
|
Olny one fix from this patch was aplayd because other was fixed few days
|
||||||
before :)
|
before :)
|
||||||
shadow-4.0.0-owl-check_names.diff
|
shadow-4.0.0-owl-check_names.diff
|
||||||
Merge only prat this patch with checking login name matching; checking
|
Merge only prat this patch with checking login name matching; checking
|
||||||
@@ -1402,7 +957,7 @@ shadow-4.0.0 => shadow-4.0.1
|
|||||||
probably _POSIX_LOGIN_NAME_MAX from <bits/posix1_lim.h>,
|
probably _POSIX_LOGIN_NAME_MAX from <bits/posix1_lim.h>,
|
||||||
shadow-4.0.0-owl-chage-drop-priv.diff
|
shadow-4.0.0-owl-chage-drop-priv.diff
|
||||||
shadow-4.0.0-owl-pam-auth.diff
|
shadow-4.0.0-owl-pam-auth.diff
|
||||||
Merge part with reorder initialize PAM and checking if chage is runed by
|
Merge part with reorder initialize PAM and checkin is chage is runed by
|
||||||
root or not - now chage can be runed from non-root account for checking
|
root or not - now chage can be runed from non-root account for checking
|
||||||
by user own account information (if PAM enabled).
|
by user own account information (if PAM enabled).
|
||||||
- fixes for handle/print correctly 32bit uid/gid (Thorsten Kukuk <kukuk@suse.de>),
|
- fixes for handle/print correctly 32bit uid/gid (Thorsten Kukuk <kukuk@suse.de>),
|
||||||
@@ -1446,30 +1001,30 @@ shadow-20001016 => shadow-4.0.0 06-01-2002
|
|||||||
- much better automake support,
|
- much better automake support,
|
||||||
- added pt_BR man pages for gpasswd(1), groupadd(8), groupdel(8),
|
- added pt_BR man pages for gpasswd(1), groupadd(8), groupdel(8),
|
||||||
groupmod(8), shadow(5) (man pages for other nations also are welcome),
|
groupmod(8), shadow(5) (man pages for other nations also are welcome),
|
||||||
- many small fixes and updates nad improvements in man pages,
|
- mamny small fixes and updates nad improvements in man pages,
|
||||||
- applied Debian patch to man pages for shadowconfig,
|
- aplayed Debian patch to man pages for shadowconfig,
|
||||||
- remove limit to 6 chars logged tty name (012_libmisc_sulog.c.diff Debian
|
- remove limit to 6 chars logged tty name (012_libmisc_sulog.c.diff Debian
|
||||||
patch).
|
patch).
|
||||||
|
|
||||||
shadow-20001012 -> shadow-20001016:
|
shadow-20001012 -> shadow-20001016:
|
||||||
- conditionally disabled body reload_nscd() because not every
|
- conditionaly disabled body reload_nscd() because not every
|
||||||
version of nscd can handle it (this can be enabled by define
|
version of nscd can handle it (this can be enabled by define
|
||||||
ENABLE_NSCD_SIGHUP) (Marek Michałkiewicz <marekm@linux.org.pl>)
|
ENABLE_NSCD_SIGHUP) (Marek Michałkiewicz <marekm@linux.org.pl>)
|
||||||
- fixes on autoconf/automake level for dist target,
|
- fixes on autoconf/automake level for dist target,
|
||||||
- Julianne F. Haugh new contact address.
|
- Julianne F. Haugh new contact adress.
|
||||||
|
|
||||||
shadow-20000902 => shadow-20001012
|
shadow-20000902 => shadow-20001012
|
||||||
|
|
||||||
- removed /redhat directory with obsoleted files (partially rewritten spec
|
- removed /redhat directory with obsoleted files (partialy rewrited spec
|
||||||
file is now in root directory),
|
file is now in root directory),
|
||||||
- applied shadow-19990827-group.patch patch from RH wich prevents adduser
|
- aplayed shadow-19990827-group.patch patch from RH wich prevents adduser
|
||||||
overwrite previously existing groups in adduser,
|
overwrite previously existing groups in adduser,
|
||||||
- added PAM support for chage (bind to "chage" PAM config file) also
|
- added PAM support for chage (bind to "chage" PAM config file) also
|
||||||
added PAM support for all other small tools like chpasswd, groupadd,
|
added PAM support for all other small tools like chpasswd, groupadd,
|
||||||
groupdel, groupmod, newusers, useradd, userdel, usermod (bind to common
|
groupdel, groupmod, newusers, useradd, userdel, usermod (bind to common
|
||||||
"shadow" PAM config file) - this modifications mainly based on
|
"shadow" PAM config file) - this modificaytions mainly based on
|
||||||
modifications prepared by Janek Rękojarski <baggins@pld.org.pl>,
|
modifications prepared by Janek Rękojarski <baggins@pld.org.pl>,
|
||||||
- many small fixes and improvements in automake (mow "make dist"
|
- many small fixes and improvments in automake (mow "make dist"
|
||||||
works correctly),
|
works correctly),
|
||||||
- added cs translation (Jiri Pavlovsky <Jiri.Pavlovsky@ff.cuni.cz>).
|
- added cs translation (Jiri Pavlovsky <Jiri.Pavlovsky@ff.cuni.cz>).
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
Shadow SITES
|
||||||
|
============
|
||||||
|
|
||||||
|
FTP site
|
||||||
|
ftp://pkg-shadow.alioth.debian.org/pub/pkg-shadow
|
||||||
|
|
||||||
|
SVN repository
|
||||||
|
anonymous read only access: svn://svn.debian.org/pkg-shadow/
|
||||||
|
|
||||||
|
SVN web interface
|
||||||
|
http://svn.debian.org/wsvn/pkg-shadow
|
||||||
|
|
||||||
|
Mailing lists
|
||||||
|
for general discuss: pkg-shadow-devel@lists.alioth.debian.org
|
||||||
|
commit list: pkg-shadow-commits@lists.alioth.debian.org
|
||||||
|
|
||||||
|
Mailing lists subscription
|
||||||
|
http://lists.alioth.debian.org/mailman/listinfo/pkg-shadow-devel
|
||||||
|
http://lists.alioth.debian.org/mailman/listinfo/pkg-shadow-commits
|
||||||
|
|
||||||
|
Mailing lists archives:
|
||||||
|
http://lists.alioth.debian.org/pipermail/pkg-shadow-devel/
|
||||||
|
http://lists.alioth.debian.org/pipermail/pkg-shadow-commits/
|
||||||
|
|
||||||
|
S/Key support:
|
||||||
|
Shadow can be built with S/Key support using the S/Key package from:
|
||||||
|
|
||||||
|
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libskey/
|
||||||
|
or
|
||||||
|
http://gentoo.osuosl.org/distfiles/skey-1.1.5.tar.bz2
|
||||||
|
|
||||||
|
Authors and contributors
|
||||||
|
========================
|
||||||
|
|
||||||
|
Thanks to at least the following people for sending me patches, bug
|
||||||
|
reports and various comments. This list may be incomplete, I received
|
||||||
|
a lot of mail...
|
||||||
|
|
||||||
|
|
||||||
|
Adam Rudnicki <adam@v-lo.krakow.pl>
|
||||||
|
Alan Curry <pacman@tardis.mars.net>
|
||||||
|
Alexander O. Yuriev <alex@bach.cis.temple.edu>
|
||||||
|
Algis Rudys <arudys@rice.edu>
|
||||||
|
Andreas Jaeger <aj@arthur.rhein-neckar.de>
|
||||||
|
Aniello Del Sorbo <anidel@edu-gw.dia.unisa.it>
|
||||||
|
Anton Gluck <gluc@midway.uchicago.edu>
|
||||||
|
Arkadiusz Miskiewicz <misiek@pld.org.pl>
|
||||||
|
Ben Collins <bcollins@debian.org>
|
||||||
|
Brian R. Gaeke <brg@dgate.org>
|
||||||
|
Calle Karlsson <ckn@kash.se>
|
||||||
|
Chip Rosenthal <chip@unicom.com>
|
||||||
|
Chris Evans <lady0110@sable.ox.ac.uk>
|
||||||
|
Cristian Gafton <gafton@sorosis.ro>
|
||||||
|
Darcy Boese <possum@chardonnay.niagara.com>
|
||||||
|
Dave Hagewood <admin@arrowweb.com>
|
||||||
|
David A. Holland <dholland@hcs.harvard.edu>
|
||||||
|
David Frey <David.Frey@lugs.ch>
|
||||||
|
Ed Carp <ecarp@netcom.com>
|
||||||
|
Floody <flood@evcom.net>
|
||||||
|
Frank Denis <j@4u.net>
|
||||||
|
George Kraft IV <gk4@us.ibm.com>
|
||||||
|
Greg Mortensen <loki@world.std.com>
|
||||||
|
Guido van Rooij
|
||||||
|
Guy Maor <maor@debian.org>
|
||||||
|
Hrvoje Dogan <hdogan@bjesomar.srce.hr>
|
||||||
|
Janos Farkas <chexum@bankinf.banki.hu>
|
||||||
|
Jay Soffian <jay@lw.net>
|
||||||
|
Jesse Thilo <Jesse.Thilo@pobox.com>
|
||||||
|
Joey Hess <joey@kite.ml.org>
|
||||||
|
John Adelsberger <jja@umr.edu>
|
||||||
|
Jonathan Hankins <jhankins@mailserv.homewood.k12.al.us>
|
||||||
|
Jon Lewis <jlewis@lewis.org>
|
||||||
|
Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
|
||||||
|
Judd Bourgeois <shagboy@bluesky.net>
|
||||||
|
Juergen Heinzl <unicorn@noris.net>
|
||||||
|
Juha Virtanen <jiivee@iki.fi>
|
||||||
|
Julianne Frances Haugh <jockgrrl@ix.netcom.com>
|
||||||
|
Leonard N. Zubkoff <lnz@dandelion.com>
|
||||||
|
Luca Berra <bluca@www.polimi.it>
|
||||||
|
Lutz Schwalowsky <schwalow@mineralogie.uni-hamburg.de>
|
||||||
|
Marc Ewing <marc@redhat.com>
|
||||||
|
Martin Bene <mb@sime.com>
|
||||||
|
Martin Mares <mj@gts.cz>
|
||||||
|
Michael Meskes <meskes@topsystem.de>
|
||||||
|
Michael Talbot-Wilson <mike@calypso.bns.com.au>
|
||||||
|
Mike Pakovic <mpakovic@users.southeast.net>
|
||||||
|
Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
|
||||||
|
Pavel Machek <pavel@bug.ucw.cz>
|
||||||
|
Phillip Street
|
||||||
|
Rafał Maszkowski <rzm@icm.edu.pl>
|
||||||
|
Rani Chouha <ranibey@smartec.com>
|
||||||
|
Sami Kerola <kerolasa@rocketmail.com>
|
||||||
|
Shane Watts <shane@nexus.mlckew.edu.au>
|
||||||
|
Steve M. Robbins <steve@nyongwa.montreal.qc.ca>
|
||||||
|
Thorsten Kukuk <kukuk@suse.de>
|
||||||
|
Tim Hockin <thockin@eagle.ais.net>
|
||||||
|
Timo Karjalainen <timok@iki.fi>
|
||||||
|
Ulisses Alonso Camaro <ulisses@pusa.eleinf.uv.es>
|
||||||
|
Werner Fink <werner@suse.de>
|
||||||
|
|
||||||
|
Maintainers
|
||||||
|
===========
|
||||||
|
|
||||||
|
Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2006)
|
||||||
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# shadow-utils
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
The shadow-utils package includes the necessary programs for
|
|
||||||
converting UNIX password files to the shadow password format, plus
|
|
||||||
programs for managing user and group accounts. The pwconv command
|
|
||||||
converts passwords to the shadow password format. The pwunconv command
|
|
||||||
unconverts shadow passwords and generates a passwd file (a standard
|
|
||||||
UNIX password file). The pwck command checks the integrity of password
|
|
||||||
and shadow files. The lastlog command prints out the last login times
|
|
||||||
for all users. The useradd, userdel, and usermod commands are used for
|
|
||||||
managing user accounts. The groupadd, groupdel, and groupmod commands
|
|
||||||
are used for managing group accounts.
|
|
||||||
|
|
||||||
## Sites
|
|
||||||
* [Homepage](https://github.com/shadow-maint/shadow)
|
|
||||||
* [Issue tracker](https://github.com/shadow-maint/shadow/issues)
|
|
||||||
* [Releases](https://github.com/shadow-maint/shadow/releases)
|
|
||||||
|
|
||||||
## Contacts
|
|
||||||
There are several ways to contact us:
|
|
||||||
* [the general discussion mailing list](
|
|
||||||
https://alioth-lists.debian.net/mailman/listinfo/pkg-shadow-devel)
|
|
||||||
* the #shadow IRC channel on libera.chat:
|
|
||||||
* irc://irc.libera.chat/shadow
|
|
||||||
|
|
||||||
### Mailing archives
|
|
||||||
* [the general discussion mailing list archive](
|
|
||||||
https://alioth-lists.debian.net/pipermail/pkg-shadow-devel/)
|
|
||||||
* [the commit mailing list archive](
|
|
||||||
https://alioth-lists-archive.debian.net/pipermail/pkg-shadow-commits/),
|
|
||||||
only used for historical purposes
|
|
||||||
|
|
||||||
## Contributions
|
|
||||||
|
|
||||||
Contributions are welcome. Follow the
|
|
||||||
[guidelines](doc/contributions/introduction.md) before posting any patches.
|
|
||||||
|
|
||||||
## Authors and maintainers
|
|
||||||
Authors and maintainers are listed in [AUTHORS.md](
|
|
||||||
https://github.com/shadow-maint/shadow/blob/master/AUTHORS.md).
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
At the moment only the latest release is supported.
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Security vulnerabilities may be reported to
|
|
||||||
* Serge Hallyn <serge@hallyn.com> (B175CFA98F192AF2)
|
|
||||||
* Christian Brauner <christian@brauner.io> (4880B8C9BD0E5106FC070F4F7B3C391EFEA93624)
|
|
||||||
* Iker Pedrosa <ipedrosa@redhat.com> (4E80EF49C7987B6DE2F81F5005079C6C3A653E57)
|
|
||||||
@@ -1,45 +1,11 @@
|
|||||||
* Create a common usage function that'd take the array of
|
passwd -l should lock the password, not the account.
|
||||||
long options and an array of descriptions and output that so things would
|
|
||||||
be standardized across the utils.
|
|
||||||
Usage strings should be normalized and split first.
|
|
||||||
Investigate optparse.
|
|
||||||
|
|
||||||
|
vipw: Test SHADOWGRP support before using gshadow features.
|
||||||
|
|
||||||
/etc/default/useradd
|
PAM: add support for customization of the PAM support (i.e. support the
|
||||||
* GROUP=1000 should accept a group name.
|
Debian PAM configuration)
|
||||||
|
|
||||||
Check when RLOGIN is enabled if ruserok() exists
|
PAM: check if a non-interactive conversation function could be used to
|
||||||
|
|
||||||
Move selinux_file_context out of lib/copydir.c
|
|
||||||
|
|
||||||
Review hardcoded root account?
|
|
||||||
|
|
||||||
review all call to strto
|
|
||||||
|
|
||||||
lib/cleanup_user.c
|
|
||||||
cleanup needed (cleanup_report_add_user* not used)
|
|
||||||
|
|
||||||
|
|
||||||
libxcrypt support
|
|
||||||
* http://wiki.linuxfromscratch.org/patches/browser/trunk/shadow/shadow-4.0.18.1-owl_blowfish-1.patch
|
|
||||||
|
|
||||||
implement getlong, getulong.
|
|
||||||
avoid atoi, atol, atoul, strtol, strtoul, ...
|
|
||||||
|
|
||||||
manpages: comment the RLOGIN parts
|
|
||||||
|
|
||||||
Replace build_list (in lib/gshadow.c) and list (in lib/sgetgrent.c) by
|
|
||||||
comma_to_list()
|
|
||||||
|
|
||||||
Revert the modified files if all files could not be changed.
|
|
||||||
* or warn and indicate which files were modified and which were not.
|
|
||||||
* check the order the files are modified.
|
|
||||||
|
|
||||||
report nscd_flush_cache failures?
|
|
||||||
call nscd from the programs or from lib (commonio?)
|
|
||||||
|
|
||||||
PAM: check if a non-interactive conversation function could be used to set
|
|
||||||
the password in chpasswd and newusers
|
|
||||||
|
|
||||||
WITH_SELINUX
|
WITH_SELINUX
|
||||||
- review all tools to check that the strategies are consistent
|
- review all tools to check that the strategies are consistent
|
||||||
@@ -47,20 +13,33 @@ WITH_SELINUX
|
|||||||
chage, chfn, chsh: same change needed as in passwd.
|
chage, chfn, chsh: same change needed as in passwd.
|
||||||
- probably need moving check_selinux_access to a separate file.
|
- probably need moving check_selinux_access to a separate file.
|
||||||
|
|
||||||
|
man useradd
|
||||||
|
document default behavior for GROUP
|
||||||
|
remove "The default group number is 1 or whatever is..."
|
||||||
|
|
||||||
|
useradd manpage
|
||||||
|
- add -k option
|
||||||
|
- mention that -o require -u
|
||||||
|
|
||||||
testsuite
|
testsuite
|
||||||
- newgrp
|
- newgrp
|
||||||
- test with unknown user's GID
|
- test with unknown user's GID
|
||||||
|
|
||||||
newusers
|
newusers
|
||||||
- add logging to SYSLOG & AUDIT
|
- add logging to SYSLOG & AUDIT
|
||||||
- use CREATE_HOME
|
|
||||||
- Add a -Z option (see useradd / usermod)
|
faillog
|
||||||
|
- accept numerical user and range of users
|
||||||
|
|
||||||
Document when/where option appeared, document whether an option is standard
|
Document when/where option appeared, document whether an option is standard
|
||||||
or not.
|
or not.
|
||||||
|
|
||||||
|
depends rules for the manpages
|
||||||
|
|
||||||
Check all the expiry semantics
|
Check all the expiry semantics
|
||||||
|
|
||||||
|
Add options --crypt-method and --sha-rounds to gpasswd
|
||||||
|
|
||||||
ALL:
|
ALL:
|
||||||
- move base passwd/shadow/group/gshadow operation to module for allow write
|
- move base passwd/shadow/group/gshadow operation to module for allow write
|
||||||
different backend modules for db, NIS, LDAP and others. Default backend it
|
different backend modules for db, NIS, LDAP and others. Default backend it
|
||||||
@@ -70,58 +49,38 @@ ALL:
|
|||||||
passwd have old piece of code with handling -r option and it will be good
|
passwd have old piece of code with handling -r option and it will be good
|
||||||
finish this and propagate on other shadow tools for allow operate on other
|
finish this and propagate on other shadow tools for allow operate on other
|
||||||
user databases by well known tools.
|
user databases by well known tools.
|
||||||
- Protect against signals. Register do_cleanups in a signal handler.
|
|
||||||
|
|
||||||
- login.defs
|
|
||||||
- generate depending on configuration
|
|
||||||
|
|
||||||
- useradd:
|
- useradd:
|
||||||
- add handle create user mail spool in maildir format.
|
- add handle create user mail spool in maildir format.
|
||||||
- Add support for -k in -D mode
|
|
||||||
- Add support for -K in -D mode
|
- add handle -n switch in groups and id command for allow query is
|
||||||
- Add option to create or not the mail spool (and set the default in -D
|
group/user with specified id/gid exist - this will be very usable
|
||||||
mode)
|
on automation in packages for query/check is group/user exist in system
|
||||||
- Change -l to reset the entry if an entry was already there
|
or not,
|
||||||
- set the mask in mkdir?
|
|
||||||
|
- groupmems:
|
||||||
|
- need some work on add PAM and i18n support.
|
||||||
|
|
||||||
- userdel:
|
- userdel:
|
||||||
- add backup option for the removal of user resources,
|
- add backup option for the removal of user resources,
|
||||||
|
- add lookop and remove per user group.
|
||||||
- user_busy: check that the user is not running any processes.
|
- user_busy: check that the user is not running any processes.
|
||||||
- missing "deleting group" FAILED
|
|
||||||
- home dir removed, but userdel may fail and may leave the user
|
|
||||||
=> warning needed
|
|
||||||
|
|
||||||
- usermod
|
|
||||||
- add an option equivalent to useradd's -l (only when uid is changed)
|
|
||||||
- the mode of new home directories should be set according to the
|
|
||||||
original mode. Does copy_tree does this?
|
|
||||||
- user renamed, order is not kept in /etc/group (see
|
|
||||||
47_usermod-l_no_shadow_file). This is a problem when the first user is
|
|
||||||
considered as the admin.
|
|
||||||
- see mail "user ID change" on April, 15
|
|
||||||
+ fix call to chown (combination of -m and -u/-g)
|
|
||||||
+ add tests
|
|
||||||
|
|
||||||
- passwd:
|
- passwd:
|
||||||
- check combination of options (e.g. -u/-l)
|
- check combination of options (e.g. -u/-l)
|
||||||
- when -u refuse to unlock because it would create an empty password, it
|
|
||||||
should not display "Password changed."
|
|
||||||
exit instead?
|
|
||||||
|
|
||||||
- newgrp: check the USE_PAM section.
|
- newgrp: check the USE_PAM section.
|
||||||
|
|
||||||
- pwck
|
- groupmems: check reason for isgroup
|
||||||
- Add check to move passwd passwords to shadow if there is a shadow
|
|
||||||
entry (with a password).
|
|
||||||
- Add check to move passwd passwords to shadow if there is a shadow
|
|
||||||
file.
|
|
||||||
- Support an alternative /etc/tcb directory as second parameter.
|
|
||||||
- add options -g / -G to specify alternative group / gshadow files
|
|
||||||
|
|
||||||
- su
|
- newusers: doc for pw_gid not clear. Differentiate
|
||||||
- add a login.defs configuration parameter to add variables to keep in
|
pw_gid specified and exist
|
||||||
the environment with "su -l" (TERM/TERMCOLOR/...)
|
pw_gid specified but does not exist
|
||||||
|
* name
|
||||||
|
* number
|
||||||
|
pw_gid not specified.
|
||||||
|
- newusers: document what happens when no uid is specified.
|
||||||
|
- newusers: add option --system?
|
||||||
|
|
||||||
- vipw
|
-Documentation:
|
||||||
- set ACLs and XATTRs on the temporary file (and backups?)
|
* document when options were added.
|
||||||
- vipw + selinux -> use lib/selinux.c
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ AC_DEFUN([JH_PATH_XML_CATALOG],
|
|||||||
[
|
[
|
||||||
# check for the presence of the XML catalog
|
# check for the presence of the XML catalog
|
||||||
AC_ARG_WITH([xml-catalog],
|
AC_ARG_WITH([xml-catalog],
|
||||||
AS_HELP_STRING([--with-xml-catalog=CATALOG],
|
AC_HELP_STRING([--with-xml-catalog=CATALOG],
|
||||||
[path to xml catalog to use]),,
|
[path to xml catalog to use]),,
|
||||||
[with_xml_catalog=/etc/xml/catalog])
|
[with_xml_catalog=/etc/xml/catalog])
|
||||||
jh_found_xmlcatalog=true
|
jh_found_xmlcatalog=true
|
||||||
|
|||||||
+1
-4
@@ -1,13 +1,10 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
autoreconf -v -f --install || exit 1
|
autoreconf -v -f --install || exit 1
|
||||||
|
|
||||||
./configure \
|
./configure \
|
||||||
CFLAGS="-O2 -Wall" \
|
CFLAGS="-O2 -Wall" \
|
||||||
--enable-lastlog \
|
|
||||||
--enable-man \
|
--enable-man \
|
||||||
--enable-maintainer-mode \
|
--enable-maintainer-mode \
|
||||||
--enable-shared \
|
--disable-shared \
|
||||||
--without-libpam \
|
--without-libpam \
|
||||||
--with-selinux \
|
--with-selinux \
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
-795
@@ -1,795 +0,0 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
|
||||||
AC_PREREQ([2.69])
|
|
||||||
m4_define([libsubid_abi_major], 4)
|
|
||||||
m4_define([libsubid_abi_minor], 0)
|
|
||||||
m4_define([libsubid_abi_micro], 0)
|
|
||||||
m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
|
|
||||||
AC_INIT([shadow], [4.14.3], [pkg-shadow-devel@lists.alioth.debian.org], [],
|
|
||||||
[https://github.com/shadow-maint/shadow])
|
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
|
|
||||||
AC_CONFIG_MACRO_DIRS([m4])
|
|
||||||
AM_SILENT_RULES([yes])
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
|
||||||
|
|
||||||
AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major])
|
|
||||||
AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor])
|
|
||||||
AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro])
|
|
||||||
AC_SUBST([LIBSUBID_ABI], [libsubid_abi])
|
|
||||||
|
|
||||||
dnl Some hacks...
|
|
||||||
test "$prefix" = "NONE" && prefix="/usr"
|
|
||||||
test "$prefix" = "/usr" && exec_prefix=""
|
|
||||||
|
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
|
||||||
|
|
||||||
AC_ENABLE_STATIC
|
|
||||||
AC_ENABLE_SHARED
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
dnl Checks for programs.
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_LN_S
|
|
||||||
AC_PROG_YACC
|
|
||||||
LT_INIT
|
|
||||||
|
|
||||||
dnl Checks for libraries.
|
|
||||||
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_CHECK_HEADERS(crypt.h utmp.h \
|
|
||||||
termio.h sgtty.h sys/ioctl.h paths.h \
|
|
||||||
sys/capability.h sys/random.h \
|
|
||||||
gshadow.h lastlog.h rpc/key_prot.h acl/libacl.h \
|
|
||||||
attr/libattr.h attr/error_context.h)
|
|
||||||
|
|
||||||
dnl shadow now uses the libc's shadow implementation
|
|
||||||
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
|
|
||||||
|
|
||||||
AC_CHECK_FUNCS(arc4random_buf futimes \
|
|
||||||
getentropy getrandom getspnam getusershell \
|
|
||||||
initgroups lckpwdf lutimes mempcpy \
|
|
||||||
setgroups updwtmp updwtmpx innetgr \
|
|
||||||
getspnam_r \
|
|
||||||
rpmatch \
|
|
||||||
memset_explicit explicit_bzero stpecpy stpeprintf)
|
|
||||||
AC_SYS_LARGEFILE
|
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
|
|
||||||
AC_CHECK_MEMBERS([struct utmp.ut_type,
|
|
||||||
struct utmp.ut_id,
|
|
||||||
struct utmp.ut_name,
|
|
||||||
struct utmp.ut_user,
|
|
||||||
struct utmp.ut_host,
|
|
||||||
struct utmp.ut_syslen,
|
|
||||||
struct utmp.ut_addr,
|
|
||||||
struct utmp.ut_addr_v6,
|
|
||||||
struct utmp.ut_time,
|
|
||||||
struct utmp.ut_xtime,
|
|
||||||
struct utmp.ut_tv],,,[[#include <utmp.h>]])
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
|
||||||
AC_TYPE_GETGROUPS
|
|
||||||
AC_FUNC_UTIME_NULL
|
|
||||||
AC_REPLACE_FUNCS(putgrent putpwent putspent)
|
|
||||||
AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
|
|
||||||
|
|
||||||
AC_CHECK_FUNC(setpgrp)
|
|
||||||
AC_CHECK_FUNC(secure_getenv, [AC_DEFINE(HAS_SECURE_GETENV,
|
|
||||||
1,
|
|
||||||
[Defined to 1 if you have the declaration of 'secure_getenv'])])
|
|
||||||
|
|
||||||
if test "$ac_cv_header_shadow_h" = "yes"; then
|
|
||||||
AC_CACHE_CHECK(for working shadow group support,
|
|
||||||
ac_cv_libc_shadowgrp,
|
|
||||||
AC_RUN_IFELSE([AC_LANG_SOURCE([
|
|
||||||
#include <shadow.h>
|
|
||||||
#ifdef HAVE_GSHADOW_H
|
|
||||||
#include <gshadow.h>
|
|
||||||
#endif
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
struct sgrp *sg = sgetsgent("test:x::");
|
|
||||||
/* NYS libc on Red Hat 3.0.3 has broken shadow group support */
|
|
||||||
return !sg || !sg->sg_adm || !sg->sg_mem;
|
|
||||||
}]
|
|
||||||
)],
|
|
||||||
[ac_cv_libc_shadowgrp=yes],
|
|
||||||
[ac_cv_libc_shadowgrp=no],
|
|
||||||
[ac_cv_libc_shadowgrp=no]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if test "$ac_cv_libc_shadowgrp" = "yes"; then
|
|
||||||
AC_DEFINE(HAVE_SHADOWGRP, 1, [Have working shadow group support in libc])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([location of shared mail directory], shadow_cv_maildir,
|
|
||||||
[for shadow_cv_maildir in /var/mail /var/spool/mail /usr/spool/mail /usr/mail none; do
|
|
||||||
if test -d $shadow_cv_maildir; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done])
|
|
||||||
if test $shadow_cv_maildir != none; then
|
|
||||||
AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIR, "$shadow_cv_maildir",
|
|
||||||
[Location of system mail spool directory.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([location of user mail file], shadow_cv_mailfile,
|
|
||||||
[for shadow_cv_mailfile in Mailbox mailbox Mail mail .mail none; do
|
|
||||||
if test -f $HOME/$shadow_cv_mailfile; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done])
|
|
||||||
if test $shadow_cv_mailfile != none; then
|
|
||||||
AC_DEFINE_UNQUOTED(MAIL_SPOOL_FILE, "$shadow_cv_mailfile",
|
|
||||||
[Name of user's mail spool file if stored in user's home directory.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([location of utmp], shadow_cv_utmpdir,
|
|
||||||
[for shadow_cv_utmpdir in /var/run /var/adm /usr/adm /etc none; do
|
|
||||||
if test -f $shadow_cv_utmpdir/utmp; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done])
|
|
||||||
if test "$shadow_cv_utmpdir" = "none"; then
|
|
||||||
AC_MSG_WARN(utmp file not found)
|
|
||||||
fi
|
|
||||||
AC_DEFINE_UNQUOTED(_UTMP_FILE, "$shadow_cv_utmpdir/utmp",
|
|
||||||
[Path for utmp file.])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], shadow_cv_logdir,
|
|
||||||
[for shadow_cv_logdir in /var/log /var/adm /usr/adm /etc; do
|
|
||||||
if test -d $shadow_cv_logdir; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done])
|
|
||||||
AC_DEFINE_UNQUOTED(_WTMP_FILE, "$shadow_cv_logdir/wtmp",
|
|
||||||
[Path for wtmp file.])
|
|
||||||
AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$shadow_cv_logdir/lastlog",
|
|
||||||
[Path for lastlog file.])
|
|
||||||
AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$shadow_cv_logdir/faillog",
|
|
||||||
[Path for faillog file.])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([location of the passwd program], shadow_cv_passwd_dir,
|
|
||||||
[if test -f /usr/bin/passwd; then
|
|
||||||
shadow_cv_passwd_dir=/usr/bin
|
|
||||||
else
|
|
||||||
shadow_cv_passwd_dir=/bin
|
|
||||||
fi])
|
|
||||||
AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
|
|
||||||
[Path to passwd program.])
|
|
||||||
|
|
||||||
dnl XXX - quick hack, should disappear before anyone notices :).
|
|
||||||
dnl XXX - I just read the above message :).
|
|
||||||
if test "$ac_cv_func_ruserok" = "yes"; then
|
|
||||||
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.])
|
|
||||||
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(shadowgrp,
|
|
||||||
[AS_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
|
|
||||||
[case "${enableval}" in
|
|
||||||
yes) enable_shadowgrp="yes" ;;
|
|
||||||
no) enable_shadowgrp="no" ;;
|
|
||||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-shadowgrp) ;;
|
|
||||||
esac],
|
|
||||||
[enable_shadowgrp="yes"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(man,
|
|
||||||
[AS_HELP_STRING([--enable-man],
|
|
||||||
[regenerate roff man pages from Docbook @<:@default=no@:>@])],
|
|
||||||
[enable_man="${enableval}"],
|
|
||||||
[enable_man="no"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(account-tools-setuid,
|
|
||||||
[AS_HELP_STRING([--enable-account-tools-setuid],
|
|
||||||
[Install the user and group management tools setuid and authenticate the callers. This requires --with-libpam.])],
|
|
||||||
[case "${enableval}" in
|
|
||||||
yes) enable_acct_tools_setuid="yes" ;;
|
|
||||||
no) enable_acct_tools_setuid="no" ;;
|
|
||||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid)
|
|
||||||
;;
|
|
||||||
esac],
|
|
||||||
[enable_acct_tools_setuid="no"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(subordinate-ids,
|
|
||||||
[AS_HELP_STRING([--enable-subordinate-ids],
|
|
||||||
[support subordinate ids @<:@default=yes@:>@])],
|
|
||||||
[enable_subids="${enableval}"],
|
|
||||||
[enable_subids="maybe"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(lastlog,
|
|
||||||
[AS_HELP_STRING([--enable-lastlog],
|
|
||||||
[enable lastlog @<:@default=no@:>@])],
|
|
||||||
[enable_lastlog="${enableval}"],
|
|
||||||
[enable_lastlog="no"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(logind,
|
|
||||||
[AS_HELP_STRING([--enable-logind],
|
|
||||||
[enable logind @<:@default=yes@:>@])],
|
|
||||||
[enable_logind="${enableval}"],
|
|
||||||
[enable_logind="yes"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_WITH(audit,
|
|
||||||
[AS_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
|
|
||||||
[with_audit=$withval], [with_audit=maybe])
|
|
||||||
AC_ARG_WITH(libpam,
|
|
||||||
[AS_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
|
|
||||||
[with_libpam=$withval], [with_libpam=maybe])
|
|
||||||
AC_ARG_WITH(btrfs,
|
|
||||||
[AS_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if found@:>@])],
|
|
||||||
[with_btrfs=$withval], [with_btrfs=maybe])
|
|
||||||
AC_ARG_WITH(selinux,
|
|
||||||
[AS_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
|
|
||||||
[with_selinux=$withval], [with_selinux=maybe])
|
|
||||||
AC_ARG_WITH(acl,
|
|
||||||
[AS_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
|
|
||||||
[with_acl=$withval], [with_acl=maybe])
|
|
||||||
AC_ARG_WITH(attr,
|
|
||||||
[AS_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
|
|
||||||
[with_attr=$withval], [with_attr=maybe])
|
|
||||||
AC_ARG_WITH(skey,
|
|
||||||
[AS_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
|
|
||||||
[with_skey=$withval], [with_skey=no])
|
|
||||||
AC_ARG_WITH(tcb,
|
|
||||||
[AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
|
|
||||||
[with_tcb=$withval], [with_tcb=maybe])
|
|
||||||
AC_ARG_WITH(libcrack,
|
|
||||||
[AS_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])],
|
|
||||||
[with_libcrack=$withval], [with_libcrack=no])
|
|
||||||
AC_ARG_WITH(sha-crypt,
|
|
||||||
[AS_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
|
|
||||||
[with_sha_crypt=$withval], [with_sha_crypt=yes])
|
|
||||||
AC_ARG_WITH(bcrypt,
|
|
||||||
[AS_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])],
|
|
||||||
[with_bcrypt=$withval], [with_bcrypt=no])
|
|
||||||
AC_ARG_WITH(yescrypt,
|
|
||||||
[AS_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])],
|
|
||||||
[with_yescrypt=$withval], [with_yescrypt=no])
|
|
||||||
AC_ARG_WITH(nscd,
|
|
||||||
[AS_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
|
|
||||||
[with_nscd=$withval], [with_nscd=yes])
|
|
||||||
AC_ARG_WITH(sssd,
|
|
||||||
[AS_HELP_STRING([--with-sssd], [enable support for flushing sssd caches @<:@default=yes@:>@])],
|
|
||||||
[with_sssd=$withval], [with_sssd=yes])
|
|
||||||
AC_ARG_WITH(group-name-max-length,
|
|
||||||
[AS_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=32@:>@])],
|
|
||||||
[with_group_name_max_length=$withval], [with_group_name_max_length=yes])
|
|
||||||
AC_ARG_WITH(su,
|
|
||||||
[AS_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
|
|
||||||
[with_su=$withval], [with_su=yes])
|
|
||||||
AC_ARG_WITH(libbsd,
|
|
||||||
[AS_HELP_STRING([--with-libbsd], [use libbsd support @<:@default=yes if found@:>@])],
|
|
||||||
[with_libbsd=$withval], [with_libbsd=yes])
|
|
||||||
|
|
||||||
if test "$with_group_name_max_length" = "no" ; then
|
|
||||||
with_group_name_max_length=0
|
|
||||||
elif test "$with_group_name_max_length" = "yes" ; then
|
|
||||||
with_group_name_max_length=32
|
|
||||||
fi
|
|
||||||
AC_DEFINE_UNQUOTED(GROUP_NAME_MAX_LENGTH, $with_group_name_max_length, [max group name length])
|
|
||||||
AC_SUBST(GROUP_NAME_MAX_LENGTH)
|
|
||||||
GROUP_NAME_MAX_LENGTH="$with_group_name_max_length"
|
|
||||||
|
|
||||||
AM_CONDITIONAL(USE_SHA_CRYPT, test "x$with_sha_crypt" = "xyes")
|
|
||||||
if test "$with_sha_crypt" = "yes"; then
|
|
||||||
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
|
|
||||||
if test "$with_bcrypt" = "yes"; then
|
|
||||||
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes")
|
|
||||||
if test "$with_yescrypt" = "yes"; then
|
|
||||||
AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$with_nscd" = "yes"; then
|
|
||||||
AC_CHECK_FUNC(posix_spawn,
|
|
||||||
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
|
|
||||||
[AC_MSG_ERROR([posix_spawn is needed for nscd support])])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$with_sssd" = "yes"; then
|
|
||||||
AC_CHECK_FUNC(posix_spawn,
|
|
||||||
[AC_DEFINE(USE_SSSD, 1, [Define to support flushing of sssd caches])],
|
|
||||||
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su]))
|
|
||||||
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
|
|
||||||
|
|
||||||
dnl Check for some functions in libc first, only if not found check for
|
|
||||||
dnl other libraries. This should prevent linking libnsl if not really
|
|
||||||
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
|
|
||||||
|
|
||||||
AC_SEARCH_LIBS(gethostbyname, nsl)
|
|
||||||
|
|
||||||
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
|
|
||||||
if test -n "$LIBECONF"; then
|
|
||||||
AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
|
|
||||||
[Directory for distribution provided configuration files])
|
|
||||||
ECONF_CPPFLAGS="-DUSE_ECONF=1"
|
|
||||||
AC_ARG_ENABLE([vendordir],
|
|
||||||
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
|
|
||||||
fi
|
|
||||||
AC_SUBST(ECONF_CPPFLAGS)
|
|
||||||
AC_SUBST(LIBECONF)
|
|
||||||
AC_SUBST([VENDORDIR], [$enable_vendordir])
|
|
||||||
if test "x$enable_vendordir" != x; then
|
|
||||||
AC_DEFINE(HAVE_VENDORDIR, 1, [Define to support vendor settings.])
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
|
|
||||||
|
|
||||||
if test "$enable_shadowgrp" = "yes"; then
|
|
||||||
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(SHADOWGRP, test "x$enable_shadowgrp" = "xyes")
|
|
||||||
|
|
||||||
if test "$enable_man" = "yes"; then
|
|
||||||
dnl
|
|
||||||
dnl Check for xsltproc
|
|
||||||
dnl
|
|
||||||
AC_PATH_PROG([XSLTPROC], [xsltproc])
|
|
||||||
if test -z "$XSLTPROC"; then
|
|
||||||
enable_man=no
|
|
||||||
AC_MSG_ERROR([xsltproc is missing.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl check for DocBook DTD and stylesheets in the local catalog.
|
|
||||||
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.5//EN],
|
|
||||||
[DocBook XML DTD V4.5], [], enable_man=no)
|
|
||||||
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
|
|
||||||
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
|
|
||||||
|
|
||||||
if test "$enable_subids" != "no"; then
|
|
||||||
dnl
|
|
||||||
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
|
|
||||||
dnl
|
|
||||||
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
|
|
||||||
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
|
|
||||||
|
|
||||||
if test "$ac_cv_sizeof_uid_t" -ge 4 && test "$ac_cv_sizeof_gid_t" -ge 4; then
|
|
||||||
AC_DEFINE(ENABLE_SUBIDS, 1, [Define to support the subordinate IDs.])
|
|
||||||
enable_subids="yes"
|
|
||||||
else
|
|
||||||
if test "x$enable_subids" = "xyes"; then
|
|
||||||
AC_MSG_ERROR([Cannot enable support the subordinate IDs on systems where gid_t or uid_t has less than 32 bits])
|
|
||||||
fi
|
|
||||||
enable_subids="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
|
|
||||||
|
|
||||||
if test "$enable_lastlog" = "yes" && test "$ac_cv_header_lastlog_h" = "yes"; then
|
|
||||||
AC_CACHE_CHECK(for ll_host in struct lastlog,
|
|
||||||
ac_cv_struct_lastlog_ll_host,
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
|
|
||||||
[struct lastlog ll; char *cp = ll.ll_host;]
|
|
||||||
)],
|
|
||||||
[ac_cv_struct_lastlog_ll_host=yes],
|
|
||||||
[ac_cv_struct_lastlog_ll_host=no]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
|
|
||||||
AC_DEFINE(HAVE_LL_HOST, 1,
|
|
||||||
[Define if struct lastlog has ll_host])
|
|
||||||
AC_DEFINE(ENABLE_LASTLOG, 1, [Define to support lastlog.])
|
|
||||||
enable_lastlog="yes"
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR([Cannot enable support for lastlog on systems where the data structures aren't available])
|
|
||||||
enable_subids="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(ENABLE_LASTLOG, test "x$enable_lastlog" != "xno")
|
|
||||||
|
|
||||||
AC_SUBST(LIBSYSTEMD)
|
|
||||||
if test "$enable_logind" = "yes"; then
|
|
||||||
AC_CHECK_LIB(systemd, sd_session_get_remote_host,
|
|
||||||
[enable_logind="yes"; [LIBSYSTEMD=-lsystemd];
|
|
||||||
AC_DEFINE(ENABLE_LOGIND, 1,
|
|
||||||
[Define to manage session support with logind.])],
|
|
||||||
[enable_logind="no"])
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(ENABLE_LOGIND, test "x$enable_logind" != "xno")
|
|
||||||
|
|
||||||
AC_SUBST(LIBCRYPT)
|
|
||||||
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
|
|
||||||
[AC_MSG_ERROR([crypt() not found])])
|
|
||||||
|
|
||||||
AC_SUBST(LIYESCRYPT)
|
|
||||||
AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt],
|
|
||||||
[AC_MSG_ERROR([crypt() not found])])
|
|
||||||
|
|
||||||
AC_SUBST(LIBBSD)
|
|
||||||
if test "$with_libbsd" != "no"; then
|
|
||||||
AC_SEARCH_LIBS([readpassphrase], [bsd], [], [
|
|
||||||
AC_MSG_ERROR([readpassphrase() is missing, either from libc or libbsd])
|
|
||||||
])
|
|
||||||
AS_IF([test "$ac_cv_search_readpassphrase" = "-lbsd"], [
|
|
||||||
PKG_CHECK_MODULES([LIBBSD], [libbsd-overlay])
|
|
||||||
])
|
|
||||||
dnl Make sure either the libc or libbsd provide the header.
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
|
|
||||||
AC_CHECK_HEADERS([readpassphrase.h])
|
|
||||||
AS_IF([test "$ac_cv_header_readpassphrase_h" != "yes"], [
|
|
||||||
AC_MSG_ERROR([readpassphrase.h is missing])
|
|
||||||
])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
AC_DEFINE(WITH_LIBBSD, 1, [Build shadow with libbsd support])
|
|
||||||
else
|
|
||||||
AC_DEFINE(WITH_LIBBSD, 0, [Build shadow without libbsd support])
|
|
||||||
AC_CHECK_FUNC(strlcpy, [], [AC_MSG_ERROR([strlcpy is required from glibc >= 2.38 or libbsd])])
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(WITH_LIBBSD, test x$with_libbsd = xyes)
|
|
||||||
|
|
||||||
AC_SUBST(LIBACL)
|
|
||||||
if test "$with_acl" != "no"; then
|
|
||||||
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
|
|
||||||
if test "$acl_header$with_acl" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
|
|
||||||
elif test "$acl_header" = "yes" ; then
|
|
||||||
AC_CHECK_LIB(acl, perm_copy_file,
|
|
||||||
[AC_CHECK_LIB(acl, perm_copy_fd,
|
|
||||||
[acl_lib="yes"],
|
|
||||||
[acl_lib="no"])],
|
|
||||||
[acl_lib="no"])
|
|
||||||
if test "$acl_lib$with_acl" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libacl not found])
|
|
||||||
elif test "$acl_lib" = "no" ; then
|
|
||||||
with_acl="no"
|
|
||||||
else
|
|
||||||
AC_DEFINE(WITH_ACL, 1,
|
|
||||||
[Build shadow with ACL support])
|
|
||||||
LIBACL="-lacl"
|
|
||||||
with_acl="yes"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
with_acl="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(LIBATTR)
|
|
||||||
if test "$with_attr" != "no"; then
|
|
||||||
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
|
|
||||||
if test "$attr_header$with_attr" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
|
|
||||||
elif test "$attr_header" = "yes" ; then
|
|
||||||
AC_CHECK_LIB(attr, attr_copy_file,
|
|
||||||
[AC_CHECK_LIB(attr, attr_copy_fd,
|
|
||||||
[attr_lib="yes"],
|
|
||||||
[attr_lib="no"])],
|
|
||||||
[attr_lib="no"])
|
|
||||||
if test "$attr_lib$with_attr" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libattr not found])
|
|
||||||
elif test "$attr_lib" = "no" ; then
|
|
||||||
with_attr="no"
|
|
||||||
else
|
|
||||||
AC_DEFINE(WITH_ATTR, 1,
|
|
||||||
[Build shadow with Extended Attributes support])
|
|
||||||
LIBATTR="-lattr"
|
|
||||||
with_attr="yes"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
with_attr="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(LIBAUDIT)
|
|
||||||
if test "$with_audit" != "no"; then
|
|
||||||
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
|
|
||||||
if test "$audit_header$with_audit" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libaudit.h is missing])
|
|
||||||
elif test "$audit_header" = "yes"; then
|
|
||||||
AC_CHECK_DECL(AUDIT_ADD_USER,,[audit_header="no"],[#include <libaudit.h>])
|
|
||||||
AC_CHECK_DECL(AUDIT_DEL_USER,,[audit_header="no"],[#include <libaudit.h>])
|
|
||||||
AC_CHECK_DECL(AUDIT_ADD_GROUP,,[audit_header="no"],[#include <libaudit.h>])
|
|
||||||
AC_CHECK_DECL(AUDIT_DEL_GROUP,,[audit_header="no"],[#include <libaudit.h>])
|
|
||||||
if test "$audit_header$with_audit" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([AUDIT_ADD_USER AUDIT_DEL_USER AUDIT_ADD_GROUP or AUDIT_DEL_GROUP missing from libaudit.h])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test "$audit_header" = "yes"; then
|
|
||||||
AC_CHECK_LIB(audit, audit_log_acct_message,
|
|
||||||
[audit_lib="yes"], [audit_lib="no"])
|
|
||||||
if test "$audit_lib$with_audit" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libaudit not found])
|
|
||||||
elif test "$audit_lib" = "no" ; then
|
|
||||||
with_audit="no"
|
|
||||||
else
|
|
||||||
AC_DEFINE(WITH_AUDIT, 1,
|
|
||||||
[Define if you want to enable Audit messages])
|
|
||||||
LIBAUDIT="-laudit"
|
|
||||||
with_audit="yes"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
with_audit="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(LIBCRACK)
|
|
||||||
if test "$with_libcrack" = "yes"; then
|
|
||||||
echo "checking cracklib flavour, don't be surprised by the results"
|
|
||||||
AC_CHECK_LIB(crack, FascistCheck,
|
|
||||||
[LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])])
|
|
||||||
AC_CHECK_LIB(crack, FascistHistory,
|
|
||||||
AC_DEFINE(HAVE_LIBCRACK_HIST, 1, [Defined if you have the ts&szs cracklib.]))
|
|
||||||
AC_CHECK_LIB(crack, FascistHistoryPw,
|
|
||||||
AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.]))
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$with_btrfs" != "no"; then
|
|
||||||
AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
|
|
||||||
[btrfs_headers="yes"], [btrfs_headers="no"])
|
|
||||||
if test "$btrfs_headers$with_btrfs" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([One of sys/statfs.h linux/magic.h linux/btrfs_tree.h is missing])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$btrfs_headers" = "yes" ; then
|
|
||||||
AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
|
|
||||||
with_btrfs="yes"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
|
|
||||||
|
|
||||||
AC_SUBST(LIBSELINUX)
|
|
||||||
AC_SUBST(LIBSEMANAGE)
|
|
||||||
if test "$with_selinux" != "no"; then
|
|
||||||
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
|
|
||||||
if test "$selinux_header$with_selinux" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([selinux/selinux.h is missing])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
|
|
||||||
if test "$semanage_header$with_selinux" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([semanage/semanage.h is missing])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$selinux_header$semanage_header" = "yesyes" ; then
|
|
||||||
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
|
|
||||||
if test "$selinux_lib$with_selinux" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libselinux not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
|
|
||||||
if test "$semanage_lib$with_selinux" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libsemanage not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$selinux_lib$semanage_lib" = "yesyes" ; then
|
|
||||||
AC_DEFINE(WITH_SELINUX, 1,
|
|
||||||
[Build shadow with SELinux support])
|
|
||||||
LIBSELINUX="-lselinux"
|
|
||||||
LIBSEMANAGE="-lsemanage"
|
|
||||||
with_selinux="yes"
|
|
||||||
else
|
|
||||||
with_selinux="no"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
with_selinux="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(LIBTCB)
|
|
||||||
if test "$with_tcb" != "no"; then
|
|
||||||
AC_CHECK_HEADERS(tcb.h, [tcb_header="yes"], [tcb_header="no"])
|
|
||||||
if test "$tcb_header$with_tcb" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([tcb.h is missing])
|
|
||||||
elif test "$tcb_header" = "yes" ; then
|
|
||||||
AC_CHECK_LIB(tcb, tcb_is_suspect, [tcb_lib="yes"], [tcb_lib="no"])
|
|
||||||
if test "$tcb_lib$with_tcb" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR([libtcb not found])
|
|
||||||
elif test "$tcb_lib" = "no" ; then
|
|
||||||
with_tcb="no"
|
|
||||||
else
|
|
||||||
AC_DEFINE(WITH_TCB, 1, [Build shadow with tcb support (incomplete)])
|
|
||||||
LIBTCB="-ltcb"
|
|
||||||
with_tcb="yes"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
with_tcb="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
|
|
||||||
|
|
||||||
AC_SUBST(LIBPAM)
|
|
||||||
if test "$with_libpam" != "no"; then
|
|
||||||
AC_CHECK_LIB(pam, pam_start,
|
|
||||||
[pam_lib="yes"], [pam_lib="no"])
|
|
||||||
if test "$pam_lib$with_libpam" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR(libpam not found)
|
|
||||||
fi
|
|
||||||
|
|
||||||
LIBPAM="-lpam"
|
|
||||||
pam_conv_function="no"
|
|
||||||
|
|
||||||
AC_CHECK_LIB(pam, openpam_ttyconv,
|
|
||||||
[pam_conv_function="openpam_ttyconv"],
|
|
||||||
AC_CHECK_LIB(pam_misc, misc_conv,
|
|
||||||
[pam_conv_function="misc_conv"; LIBPAM="$LIBPAM -lpam_misc"])
|
|
||||||
)
|
|
||||||
|
|
||||||
if test "$pam_conv_function$with_libpam" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR(PAM conversation function not found)
|
|
||||||
fi
|
|
||||||
|
|
||||||
pam_headers_found=no
|
|
||||||
AC_CHECK_HEADERS( [security/openpam.h security/pam_misc.h],
|
|
||||||
[ pam_headers_found=yes ; break ], [],
|
|
||||||
[ #include <security/pam_appl.h> ] )
|
|
||||||
if test "$pam_headers_found$with_libpam" = "noyes" ; then
|
|
||||||
AC_MSG_ERROR(PAM headers not found)
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if test "$pam_lib$pam_headers_found" = "yesyes" -a "$pam_conv_function" != "no" ; then
|
|
||||||
with_libpam="yes"
|
|
||||||
else
|
|
||||||
with_libpam="no"
|
|
||||||
unset LIBPAM
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
dnl Now with_libpam is either yes or no
|
|
||||||
if test "$with_libpam" = "yes"; then
|
|
||||||
AC_CHECK_DECLS([PAM_ESTABLISH_CRED,
|
|
||||||
PAM_DELETE_CRED,
|
|
||||||
PAM_NEW_AUTHTOK_REQD,
|
|
||||||
PAM_DATA_SILENT],
|
|
||||||
[], [], [#include <security/pam_appl.h>])
|
|
||||||
|
|
||||||
|
|
||||||
save_libs=$LIBS
|
|
||||||
LIBS="$LIBS $LIBPAM"
|
|
||||||
# We do not use AC_CHECK_FUNCS to avoid duplicated definition with
|
|
||||||
# Linux PAM.
|
|
||||||
AC_CHECK_FUNC(pam_fail_delay, [AC_DEFINE(HAS_PAM_FAIL_DELAY, 1, [Define to 1 if you have the declaration of 'pam_fail_delay'])])
|
|
||||||
LIBS=$save_libs
|
|
||||||
|
|
||||||
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
|
|
||||||
AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM conversation to use])
|
|
||||||
AM_CONDITIONAL(USE_PAM, [true])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
else
|
|
||||||
AC_DEFINE(SU_ACCESS, 1, [Define to support /etc/suauth su access control.])
|
|
||||||
AM_CONDITIONAL(USE_PAM, [false])
|
|
||||||
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$enable_acct_tools_setuid" != "no"; then
|
|
||||||
if test "$with_libpam" != "yes"; then
|
|
||||||
if test "$enable_acct_tools_setuid" = "yes"; then
|
|
||||||
AC_MSG_ERROR(PAM support is required for --enable-account-tools-setuid)
|
|
||||||
else
|
|
||||||
enable_acct_tools_setuid="no"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
enable_acct_tools_setuid="yes"
|
|
||||||
fi
|
|
||||||
if test "$enable_acct_tools_setuid" = "yes"; then
|
|
||||||
AC_DEFINE(ACCT_TOOLS_SETUID,
|
|
||||||
1,
|
|
||||||
[Define if account management tools should be installed setuid and authenticate the callers])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes")
|
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_WITH(fcaps,
|
|
||||||
[AS_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries for newuidmap/newgidmap @<:@default=no@:>@])],
|
|
||||||
[with_fcaps=$withval], [with_fcaps=no])
|
|
||||||
AM_CONDITIONAL(FCAPS, test "x$with_fcaps" = "xyes")
|
|
||||||
|
|
||||||
if test "x$with_fcaps" = "xyes"; then
|
|
||||||
AC_CHECK_PROGS(capcmd, "setcap")
|
|
||||||
if test "x$capcmd" = "x" ; then
|
|
||||||
AC_MSG_ERROR([setcap command not available])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(LIBSKEY)
|
|
||||||
AC_SUBST(LIBMD)
|
|
||||||
if test "$with_skey" = "yes"; then
|
|
||||||
AC_CHECK_LIB(md, MD5Init, [LIBMD=-lmd])
|
|
||||||
AC_CHECK_LIB(skey, skeychallenge, [LIBSKEY=-lskey],
|
|
||||||
[AC_MSG_ERROR([liskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
|
|
||||||
AC_DEFINE(SKEY, 1, [Define to support S/Key logins.])
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <skey.h>
|
|
||||||
]], [[
|
|
||||||
skeychallenge((void*)0, (void*)0, (void*)0, 0);
|
|
||||||
]])],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])],[])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CHECK_FUNC(fgetpwent_r, [AC_DEFINE(HAVE_FGETPWENT_R, 1, [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.])
|
|
||||||
|
|
||||||
AM_GNU_GETTEXT_VERSION([0.19])
|
|
||||||
AM_GNU_GETTEXT([external], [need-ngettext])
|
|
||||||
AM_CONDITIONAL(USE_NLS, test "x$USE_NLS" = "xyes")
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
|
||||||
Makefile
|
|
||||||
po/Makefile.in
|
|
||||||
doc/Makefile
|
|
||||||
man/Makefile
|
|
||||||
man/config.xml
|
|
||||||
man/po/Makefile
|
|
||||||
man/cs/Makefile
|
|
||||||
man/da/Makefile
|
|
||||||
man/de/Makefile
|
|
||||||
man/es/Makefile
|
|
||||||
man/fi/Makefile
|
|
||||||
man/fr/Makefile
|
|
||||||
man/hu/Makefile
|
|
||||||
man/id/Makefile
|
|
||||||
man/it/Makefile
|
|
||||||
man/ja/Makefile
|
|
||||||
man/ko/Makefile
|
|
||||||
man/pl/Makefile
|
|
||||||
man/pt_BR/Makefile
|
|
||||||
man/ru/Makefile
|
|
||||||
man/sv/Makefile
|
|
||||||
man/tr/Makefile
|
|
||||||
man/uk/Makefile
|
|
||||||
man/zh_CN/Makefile
|
|
||||||
man/zh_TW/Makefile
|
|
||||||
lib/Makefile
|
|
||||||
libsubid/Makefile
|
|
||||||
libsubid/subid.h
|
|
||||||
src/Makefile
|
|
||||||
contrib/Makefile
|
|
||||||
etc/Makefile
|
|
||||||
etc/pam.d/Makefile
|
|
||||||
etc/shadow-maint/Makefile
|
|
||||||
shadow.spec
|
|
||||||
])
|
|
||||||
AC_OUTPUT
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "shadow will be compiled with the following features:"
|
|
||||||
echo
|
|
||||||
echo " auditing support: $with_audit"
|
|
||||||
echo " CrackLib support: $with_libcrack"
|
|
||||||
echo " PAM support: $with_libpam"
|
|
||||||
if test "$with_libpam" = "yes"; then
|
|
||||||
echo " suid account management tools: $enable_acct_tools_setuid"
|
|
||||||
fi
|
|
||||||
echo " SELinux support: $with_selinux"
|
|
||||||
echo " BtrFS support: $with_btrfs"
|
|
||||||
echo " ACL support: $with_acl"
|
|
||||||
echo " Extended Attributes support: $with_attr"
|
|
||||||
echo " tcb support (incomplete): $with_tcb"
|
|
||||||
echo " shadow group support: $enable_shadowgrp"
|
|
||||||
echo " S/Key support: $with_skey"
|
|
||||||
echo " SHA passwords encryption: $with_sha_crypt"
|
|
||||||
echo " bcrypt passwords encryption: $with_bcrypt"
|
|
||||||
echo " yescrypt passwords encryption: $with_yescrypt"
|
|
||||||
echo " nscd support: $with_nscd"
|
|
||||||
echo " sssd support: $with_sssd"
|
|
||||||
echo " subordinate IDs support: $enable_subids"
|
|
||||||
echo " enable lastlog: $enable_lastlog"
|
|
||||||
echo " enable logind: $enable_logind"
|
|
||||||
echo " use file caps: $with_fcaps"
|
|
||||||
echo " install su: $with_su"
|
|
||||||
echo " enabled vendor dir: $enable_vendordir"
|
|
||||||
echo
|
|
||||||
+430
@@ -0,0 +1,430 @@
|
|||||||
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
AC_INIT
|
||||||
|
AM_INIT_AUTOMAKE(shadow, 4.1.2)
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
dnl Some hacks...
|
||||||
|
test "$prefix" = "NONE" && prefix="/usr"
|
||||||
|
test "$prefix" = "/usr" && exec_prefix=""
|
||||||
|
|
||||||
|
AC_GNU_SOURCE
|
||||||
|
|
||||||
|
AM_DISABLE_SHARED
|
||||||
|
AM_ENABLE_STATIC
|
||||||
|
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
dnl Checks for programs.
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_ISC_POSIX
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_YACC
|
||||||
|
AM_C_PROTOTYPES
|
||||||
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
|
dnl Checks for libraries.
|
||||||
|
|
||||||
|
dnl Checks for header files.
|
||||||
|
AC_HEADER_DIRENT
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
|
||||||
|
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
|
||||||
|
utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
|
||||||
|
locale.h rpc/key_prot.h netdb.h)
|
||||||
|
|
||||||
|
dnl shadow now uses the libc's shadow implementation
|
||||||
|
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(l64a fchmod fchown fsync getgroups gethostname getspnam \
|
||||||
|
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
|
||||||
|
memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
|
||||||
|
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
|
||||||
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_TYPE_UID_T
|
||||||
|
AC_TYPE_OFF_T
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_MODE_T
|
||||||
|
AC_HEADER_STAT
|
||||||
|
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||||
|
AC_HEADER_TIME
|
||||||
|
AC_STRUCT_TM
|
||||||
|
|
||||||
|
if test "$ac_cv_header_utmp_h" = "yes"; then
|
||||||
|
AC_CACHE_CHECK(for ut_host in struct utmp,
|
||||||
|
ac_cv_struct_utmp_ut_host,
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([#include <utmp.h>],
|
||||||
|
[struct utmp ut; char *cp = ut.ut_host;]
|
||||||
|
)],
|
||||||
|
[ac_cv_struct_utmp_ut_host=yes],
|
||||||
|
[ac_cv_struct_utmp_ut_host=no]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ac_cv_struct_utmp_ut_host" = "yes"; then
|
||||||
|
AC_DEFINE(UT_HOST, 1, [Define if you have ut_host in struct utmp.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK(for ut_user in struct utmp,
|
||||||
|
ac_cv_struct_utmp_ut_user,
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <utmp.h>],
|
||||||
|
[struct utmp ut; char *cp = ut.ut_user;]
|
||||||
|
)],
|
||||||
|
[ac_cv_struct_utmp_ut_user=yes],
|
||||||
|
[ac_cv_struct_utmp_ut_user=no]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ac_cv_struct_utmp_ut_user" = "no"; then
|
||||||
|
AC_DEFINE(ut_user, ut_name,
|
||||||
|
[Define to ut_name if struct utmp has ut_name (not ut_user).])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$ac_cv_header_lastlog_h" = "yes"; then
|
||||||
|
AC_CACHE_CHECK(for ll_host in struct lastlog,
|
||||||
|
ac_cv_struct_lastlog_ll_host,
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
|
||||||
|
[struct lastlog ll; char *cp = ll.ll_host;]
|
||||||
|
)],
|
||||||
|
[ac_cv_struct_lastlog_ll_host=yes],
|
||||||
|
[ac_cv_struct_lastlog_ll_host=no]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_LL_HOST, 1,
|
||||||
|
[Define if struct lastlog has ll_host])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Checks for library functions.
|
||||||
|
AC_TYPE_GETGROUPS
|
||||||
|
AC_TYPE_SIGNAL
|
||||||
|
AC_FUNC_UTIME_NULL
|
||||||
|
AC_FUNC_STRFTIME
|
||||||
|
AC_REPLACE_FUNCS(mkdir putgrent putpwent putspent rename rmdir)
|
||||||
|
AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
|
||||||
|
AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr)
|
||||||
|
|
||||||
|
AC_CHECK_FUNC(setpgrp)
|
||||||
|
AC_FUNC_SETPGRP
|
||||||
|
|
||||||
|
if test "$ac_cv_header_shadow_h" = "yes"; then
|
||||||
|
AC_CACHE_CHECK(for working shadow group support,
|
||||||
|
ac_cv_libc_shadowgrp,
|
||||||
|
AC_RUN_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <shadow.h>
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
struct sgrp *sg = sgetsgent("test:x::");
|
||||||
|
/* NYS libc on Red Hat 3.0.3 has broken shadow group support */
|
||||||
|
return !sg || !sg->sg_adm || !sg->sg_mem;
|
||||||
|
}]
|
||||||
|
)],
|
||||||
|
[ac_cv_libc_shadowgrp=yes],
|
||||||
|
[ac_cv_libc_shadowgrp=no],
|
||||||
|
[ac_cv_libc_shadowgrp=no]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ac_cv_libc_shadowgrp" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_SHADOWGRP, 1, [Have working shadow group support in libc])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([location of shared mail directory], shadow_cv_maildir,
|
||||||
|
[for shadow_cv_maildir in /var/mail /var/spool/mail /usr/spool/mail /usr/mail none; do
|
||||||
|
if test -d $shadow_cv_maildir; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done])
|
||||||
|
if test $shadow_cv_maildir != none; then
|
||||||
|
AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIR, "$shadow_cv_maildir",
|
||||||
|
[Location of system mail spool directory.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([location of user mail file], shadow_cv_mailfile,
|
||||||
|
[for shadow_cv_mailfile in Mailbox mailbox Mail mail .mail none; do
|
||||||
|
if test -f $HOME/$shadow_cv_mailfile; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done])
|
||||||
|
if test $shadow_cv_mailfile != none; then
|
||||||
|
AC_DEFINE_UNQUOTED(MAIL_SPOOL_FILE, "$shadow_cv_mailfile",
|
||||||
|
[Name of user's mail spool file if stored in user's home directory.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([location of utmp], shadow_cv_utmpdir,
|
||||||
|
[for shadow_cv_utmpdir in /var/run /var/adm /usr/adm /etc none; do
|
||||||
|
if test -f $shadow_cv_utmpdir/utmp; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done])
|
||||||
|
if test "$shadow_cv_utmpdir" = "none"; then
|
||||||
|
AC_MSG_WARN(utmp file not found)
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED(_UTMP_FILE, "$shadow_cv_utmpdir/utmp",
|
||||||
|
[Path for utmp file.])
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], shadow_cv_logdir,
|
||||||
|
[for shadow_cv_logdir in /var/log /var/adm /usr/adm /etc; do
|
||||||
|
if test -d $shadow_cv_logdir; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done])
|
||||||
|
AC_DEFINE_UNQUOTED(_WTMP_FILE, "$shadow_cv_logdir/wtmp",
|
||||||
|
[Path for wtmp file.])
|
||||||
|
AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$shadow_cv_logdir/lastlog",
|
||||||
|
[Path for lastlog file.])
|
||||||
|
AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$shadow_cv_logdir/faillog",
|
||||||
|
[Path for faillog file.])
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([location of the passwd program], shadow_cv_passwd_dir,
|
||||||
|
[if test -f /usr/bin/passwd; then
|
||||||
|
shadow_cv_passwd_dir=/usr/bin
|
||||||
|
else
|
||||||
|
shadow_cv_passwd_dir=/bin
|
||||||
|
fi])
|
||||||
|
AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
|
||||||
|
[Path to passwd program.])
|
||||||
|
|
||||||
|
dnl XXX - quick hack, should disappear before anyone notices :).
|
||||||
|
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().])
|
||||||
|
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.])
|
||||||
|
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(shadowgrp,
|
||||||
|
[AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) enable_shadowgrp="yes" ;;
|
||||||
|
no) enable_shadowgrp="no" ;;
|
||||||
|
*) AC_MSG_ERROR(bad value ${enableval} for --enable-shadowgrp) ;;
|
||||||
|
esac],
|
||||||
|
[enable_shadowgrp="yes"]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(man,
|
||||||
|
[AC_HELP_STRING([--enable-man],
|
||||||
|
[regenerate roff man pages from Docbook @<:@default=no@:>@])],
|
||||||
|
[enable_man=yes],
|
||||||
|
[enable_man=no]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_WITH(audit,
|
||||||
|
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
|
||||||
|
[with_audit=$withval], [with_audit=maybe])
|
||||||
|
AC_ARG_WITH(libpam,
|
||||||
|
[AC_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
|
||||||
|
[with_libpam=$withval], [with_libpam=maybe])
|
||||||
|
AC_ARG_WITH(selinux,
|
||||||
|
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
|
||||||
|
[with_selinux=$withval], [with_selinux=maybe])
|
||||||
|
AC_ARG_WITH(skey,
|
||||||
|
[AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
|
||||||
|
[with_skey=$withval], [with_skey=no])
|
||||||
|
AC_ARG_WITH(libcrack,
|
||||||
|
[AC_HELP_STRING([--with-libcrack], [use libcrack @<:@default=yes if found and if PAM not enabled@:>@])],
|
||||||
|
[with_libcrack=$withval], [with_libcrack=no])
|
||||||
|
AC_ARG_WITH(sha-crypt,
|
||||||
|
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
|
||||||
|
[with_sha_crypt=$withval], [with_sha_crypt=yes])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(USE_SHA_CRYPT, test "x$with_sha_crypt" = "xyes")
|
||||||
|
if test "$with_sha_crypt" = "yes"; then
|
||||||
|
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for some functions in libc first, only if not found check for
|
||||||
|
dnl other libraries. This should prevent linking libnsl if not really
|
||||||
|
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
|
||||||
|
|
||||||
|
AC_SEARCH_LIBS(inet_ntoa, inet)
|
||||||
|
AC_SEARCH_LIBS(socket, socket)
|
||||||
|
AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||||
|
|
||||||
|
if test "$enable_shadowgrp" = "yes"; then
|
||||||
|
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(SHADOWGRP, test "x$enable_shadowgrp" = "xyes")
|
||||||
|
|
||||||
|
if test "$enable_man" = "yes"; then
|
||||||
|
dnl
|
||||||
|
dnl Check for xsltproc
|
||||||
|
dnl
|
||||||
|
AC_PATH_PROG([XSLTPROC], [xsltproc])
|
||||||
|
if test -z "$XSLTPROC"; then
|
||||||
|
enable_man=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl check for DocBook DTD and stylesheets in the local catalog.
|
||||||
|
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.1.2//EN],
|
||||||
|
[DocBook XML DTD V4.1.2], [], enable_man=no)
|
||||||
|
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
|
||||||
|
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test x$enable_man != xno)
|
||||||
|
|
||||||
|
AC_SUBST(LIBCRYPT)
|
||||||
|
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
|
||||||
|
[AC_MSG_ERROR([crypt() not found])])
|
||||||
|
|
||||||
|
AC_SUBST(LIBAUDIT)
|
||||||
|
if test "$with_audit" != "no"; then
|
||||||
|
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
|
||||||
|
if test "$audit_header$with_audit" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR([libaudit.h is missing])
|
||||||
|
elif test "$audit_header" = "yes"; then
|
||||||
|
AC_CHECK_LIB(audit, audit_log_acct_message,
|
||||||
|
[audit_lib="yes"], [audit_lib="no"])
|
||||||
|
if test "$audit_lib$with_audit" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR([libaudit not found])
|
||||||
|
elif test "$audit_lib" = "no" ; then
|
||||||
|
with_audit="no"
|
||||||
|
else
|
||||||
|
AC_DEFINE(WITH_AUDIT, 1,
|
||||||
|
[Define if you want to enable Audit messages])
|
||||||
|
LIBAUDIT="-laudit"
|
||||||
|
with_audit="yes"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
with_audit="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(LIBCRACK)
|
||||||
|
if test "$with_libcrack" = "yes"; then
|
||||||
|
echo "checking cracklib flavour, don't be surprised by the results"
|
||||||
|
AC_CHECK_LIB(crack, FascistCheck,
|
||||||
|
[LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])])
|
||||||
|
AC_CHECK_LIB(crack, FascistHistory,
|
||||||
|
AC_DEFINE(HAVE_LIBCRACK_HIST, 1, [Defined if you have the ts&szs cracklib.]))
|
||||||
|
AC_CHECK_LIB(crack, FascistHistoryPw,
|
||||||
|
AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.]))
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(LIBSELINUX)
|
||||||
|
if test "$with_selinux" != "no"; then
|
||||||
|
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
|
||||||
|
if test "$selinux_header$with_selinux" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR([selinux/selinux.h is missing])
|
||||||
|
elif test "$selinux_header" = "yes" ; then
|
||||||
|
AC_CHECK_LIB(selinux, is_selinux_enabled,
|
||||||
|
[selinux_lib="yes"], [selinux_lib="no"])
|
||||||
|
if test "$selinux_lib$with_selinux" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR([libselinux not found])
|
||||||
|
elif test "$selinux_lib" = "no" ; then
|
||||||
|
with_selinux="no"
|
||||||
|
else
|
||||||
|
AC_DEFINE(WITH_SELINUX, 1,
|
||||||
|
[Build shadow with SELinux support])
|
||||||
|
LIBSELINUX="-lselinux"
|
||||||
|
with_selinux="yes"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
with_selinux="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(LIBPAM)
|
||||||
|
if test "$with_libpam" != "no"; then
|
||||||
|
AC_CHECK_LIB(pam, pam_start,
|
||||||
|
[pam_lib="yes"], [pam_lib="no"])
|
||||||
|
if test "$pam_lib$with_libpam" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR(libpam not found)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_LIB(pam_misc, main,
|
||||||
|
[pam_misc_lib="yes"], [pam_misc_lib="no"])
|
||||||
|
if test "$pam_misc_lib$with_libpam" = "noyes" ; then
|
||||||
|
AC_MSG_ERROR(libpam_misc not found)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$pam_lib$pam_misc_lib" = "yesyes" ; then
|
||||||
|
with_libpam="yes"
|
||||||
|
else
|
||||||
|
with_libpam="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Now with_libpam is either yes or no
|
||||||
|
if test "$with_libpam" = "yes"; then
|
||||||
|
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
|
||||||
|
AM_CONDITIONAL(USE_PAM, [true])
|
||||||
|
LIBPAM="-lpam -lpam_misc"
|
||||||
|
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
else
|
||||||
|
AC_DEFINE(SU_ACCESS, 1, [Define to support /etc/suauth su access control.])
|
||||||
|
AM_CONDITIONAL(USE_PAM, [false])
|
||||||
|
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(LIBSKEY)
|
||||||
|
AC_SUBST(LIBMD)
|
||||||
|
if test "$with_skey" = "yes"; then
|
||||||
|
AC_CHECK_LIB(md, MD5Init, [LIBMD=-lmd])
|
||||||
|
AC_CHECK_LIB(skey, skeychallenge, [LIBSKEY=-lskey],
|
||||||
|
[AC_MSG_ERROR([liskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
|
||||||
|
AC_DEFINE(SKEY, 1, [Define to support S/Key logins.])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <skey.h>
|
||||||
|
],[
|
||||||
|
skeychallenge((void*)0, (void*)0, (void*)0, 0);
|
||||||
|
],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_GNU_GETTEXT_VERSION(0.16)
|
||||||
|
AM_GNU_GETTEXT([external], [need-ngettext])
|
||||||
|
AM_CONDITIONAL(USE_NLS, test "x$USE_NLS" = "xyes")
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
po/Makefile.in
|
||||||
|
doc/Makefile
|
||||||
|
man/Makefile
|
||||||
|
man/po/Makefile.in
|
||||||
|
man/cs/Makefile
|
||||||
|
man/de/Makefile
|
||||||
|
man/es/Makefile
|
||||||
|
man/fi/Makefile
|
||||||
|
man/fr/Makefile
|
||||||
|
man/hu/Makefile
|
||||||
|
man/id/Makefile
|
||||||
|
man/it/Makefile
|
||||||
|
man/ja/Makefile
|
||||||
|
man/ko/Makefile
|
||||||
|
man/pl/Makefile
|
||||||
|
man/pt_BR/Makefile
|
||||||
|
man/ru/Makefile
|
||||||
|
man/sv/Makefile
|
||||||
|
man/tr/Makefile
|
||||||
|
man/zh_CN/Makefile
|
||||||
|
man/zh_TW/Makefile
|
||||||
|
libmisc/Makefile
|
||||||
|
lib/Makefile
|
||||||
|
src/Makefile
|
||||||
|
contrib/Makefile
|
||||||
|
etc/Makefile
|
||||||
|
etc/pam.d/Makefile
|
||||||
|
shadow.spec
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "shadow will be compiled with the following features:"
|
||||||
|
echo
|
||||||
|
echo " auditing support: $with_audit"
|
||||||
|
echo " CrackLib support: $with_libcrack"
|
||||||
|
echo " PAM support: $with_libpam"
|
||||||
|
echo " SELinux support: $with_selinux"
|
||||||
|
echo " shadow group support: $enable_shadowgrp"
|
||||||
|
echo " S/Key support: $with_skey"
|
||||||
|
echo " SHA passwords encryption: $with_sha_crypt"
|
||||||
|
echo
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# This is a dummy Makefile.am to get automake work flawlessly,
|
# This is a dummy Makefile.am to get automake work flawlessly,
|
||||||
# and also cooperate to make a distribution for `make dist'
|
# and also cooperate to make a distribution for `make dist'
|
||||||
|
|
||||||
EXTRA_DIST = README adduser.c adduser.sh adduser2.sh \
|
EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \
|
||||||
atudel groupmems.shar shadow-anonftp.patch \
|
atudel groupmems.shar pwdauth.c shadow-anonftp.patch \
|
||||||
udbachk.tgz
|
udbachk.tgz
|
||||||
|
|||||||
@@ -0,0 +1,300 @@
|
|||||||
|
/****
|
||||||
|
** 03/17/96
|
||||||
|
** hacked a bit more, removed unused code, cleaned up for gcc -Wall.
|
||||||
|
** --marekm
|
||||||
|
**
|
||||||
|
** 02/26/96
|
||||||
|
** modified to call shadow utils (useradd,chage,passwd) on shadowed
|
||||||
|
** systems - Cristian Gafton, gafton@sorosis.ro
|
||||||
|
**
|
||||||
|
** 6/27/95
|
||||||
|
** shadow-adduser 1.4:
|
||||||
|
**
|
||||||
|
** now it copies the /etc/skel dir into the person's dir,
|
||||||
|
** makes the mail folders, changed some defaults and made a 'make
|
||||||
|
** install' just for the hell of it.
|
||||||
|
**
|
||||||
|
** Greg Gallagher
|
||||||
|
** CIN.Net
|
||||||
|
**
|
||||||
|
** 1/28/95
|
||||||
|
** shadow-adduser 1.3:
|
||||||
|
**
|
||||||
|
** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
|
||||||
|
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
|
||||||
|
** It was such a stupid bug that I would have never seen it myself.
|
||||||
|
**
|
||||||
|
** Brandon
|
||||||
|
*****
|
||||||
|
** 01/27/95
|
||||||
|
**
|
||||||
|
** shadow-adduser 1.2:
|
||||||
|
** I took the C source from adduser-shadow (credits are below) and made
|
||||||
|
** it a little more worthwhile. Many small changes... Here's
|
||||||
|
** the ones I can remember:
|
||||||
|
**
|
||||||
|
** Removed support for non-shadowed systems (if you don't have shadow,
|
||||||
|
** use the original adduser, don't get this shadow version!)
|
||||||
|
** Added support for the correct /etc/shadow fields (Min days before
|
||||||
|
** password change, max days before password change, Warning days,
|
||||||
|
** and how many days from expiry date does the account go invalid)
|
||||||
|
** The previous version just left all of those fields blank.
|
||||||
|
** There is still one field left (expiry date for the account, period)
|
||||||
|
** which I have left blank because I do not use it and didn't want to
|
||||||
|
** spend any more time on this. I'm sure someone will put it in and
|
||||||
|
** tack another plethora of credits on here. :)
|
||||||
|
** Added in the password date field, which should always reflect the last
|
||||||
|
** date the password was changed, for expiry purposes. "passwd" always
|
||||||
|
** updates this field, so the adduser program should set it up right
|
||||||
|
** initially (or a user could keep thier initial password forever ;)
|
||||||
|
** The number is in days since Jan 1st, 1970.
|
||||||
|
**
|
||||||
|
** Have fun with it, and someone please make
|
||||||
|
** a real version(this is still just a hack)
|
||||||
|
** for us all to use (and Email it to me???)
|
||||||
|
**
|
||||||
|
** Brandon
|
||||||
|
** photon@usis.com
|
||||||
|
**
|
||||||
|
*****
|
||||||
|
** adduser 1.0: add a new user account (For systems not using shadow)
|
||||||
|
** With a nice little interface and a will to do all the work for you.
|
||||||
|
**
|
||||||
|
** Craig Hagan
|
||||||
|
** hagan@opine.cs.umass.edu
|
||||||
|
**
|
||||||
|
** Modified to really work, look clean, and find unused uid by Chris Cappuccio
|
||||||
|
** chris@slinky.cs.umass.edu
|
||||||
|
**
|
||||||
|
*****
|
||||||
|
**
|
||||||
|
** 01/19/95
|
||||||
|
**
|
||||||
|
** FURTHER modifications to enable shadow passwd support (kludged, but
|
||||||
|
** no more so than the original) by Dan Crowson - dcrowson@mo.net
|
||||||
|
**
|
||||||
|
** Search on DAN for all changes...
|
||||||
|
**
|
||||||
|
*****
|
||||||
|
**
|
||||||
|
** cc -O -o adduser adduser.c
|
||||||
|
** Use gcc if you have it... (political reasons beyond my control) (chris)
|
||||||
|
**
|
||||||
|
** I've gotten this program to work with success under Linux (without
|
||||||
|
** shadow) and SunOS 4.1.3. I would assume it should work pretty well
|
||||||
|
** on any system that uses no shadow. (chris)
|
||||||
|
**
|
||||||
|
** If you have no crypt() then try
|
||||||
|
** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c
|
||||||
|
** I'm not sure how login operates with no crypt()... I guess
|
||||||
|
** the same way we're doing it here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */
|
||||||
|
#define DEFAULT_HOME "/home"
|
||||||
|
#define USERADD_PATH "/usr/sbin/useradd"
|
||||||
|
#define CHAGE_PATH "/usr/sbin/chage"
|
||||||
|
#define PASSWD_PATH "/usr/bin/passwd"
|
||||||
|
#define DEFAULT_GROUP 100
|
||||||
|
|
||||||
|
#define DEFAULT_MAX_PASS 60
|
||||||
|
#define DEFAULT_WARN_PASS 10
|
||||||
|
/* if you use this feature, you will get a lot of complaints from users
|
||||||
|
who rarely use their accounts :) (something like 3 months would be
|
||||||
|
more reasonable) --marekm */
|
||||||
|
#define DEFAULT_USER_DIE /* 10 */ 0
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
char foo[32];
|
||||||
|
char uname[9],person[32],dir[32],shell[32];
|
||||||
|
unsigned int group,min_pass,max_pass,warn_pass,user_die;
|
||||||
|
/* the group and uid of the new user */
|
||||||
|
int bad=0,done=0,correct=0,gets_warning=0;
|
||||||
|
char cmd[255];
|
||||||
|
struct group *grp;
|
||||||
|
|
||||||
|
/* flags, in order:
|
||||||
|
* bad to see if the username is in /etc/passwd, or if strange stuff has
|
||||||
|
* been typed if the user might be put in group 0
|
||||||
|
* done allows the program to exit when a user has been added
|
||||||
|
* correct loops until a password is found that isn't in /etc/passwd
|
||||||
|
* gets_warning allows the fflush to be skipped for the first gets
|
||||||
|
* so that output is still legible
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The real program starts HERE! */
|
||||||
|
|
||||||
|
if(geteuid()!=0)
|
||||||
|
{
|
||||||
|
printf("It seems you don't have access to add a new user. Try\n");
|
||||||
|
printf("logging in as root or su root to gain super-user access.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity checks
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(grp=getgrgid(DEFAULT_GROUP))){
|
||||||
|
printf("Error: the default group %d does not exist on this system!\n",
|
||||||
|
DEFAULT_GROUP);
|
||||||
|
printf("adduser must be recompiled.\n");
|
||||||
|
exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
while(!correct) { /* loop until a "good" uname is chosen */
|
||||||
|
while(!done) {
|
||||||
|
printf("\nLogin to add (^C to quit): ");
|
||||||
|
if(gets_warning) /* if the warning was already shown */
|
||||||
|
fflush(stdout); /* fflush stdout, otherwise set the flag */
|
||||||
|
else
|
||||||
|
gets_warning=1;
|
||||||
|
|
||||||
|
gets(uname);
|
||||||
|
if(!strlen(uname)) {
|
||||||
|
printf("Empty input.\n");
|
||||||
|
done=0;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* what I saw here before made me think maybe I was running DOS */
|
||||||
|
/* might this be a solution? (chris) */
|
||||||
|
if (getpwnam(uname) != NULL) {
|
||||||
|
printf("That name is in use, choose another.\n");
|
||||||
|
done=0;
|
||||||
|
} else
|
||||||
|
done=1;
|
||||||
|
}; /* done, we have a valid new user name */
|
||||||
|
|
||||||
|
/* all set, get the rest of the stuff */
|
||||||
|
printf("\nEditing information for new user [%s]\n",uname);
|
||||||
|
|
||||||
|
printf("\nFull Name [%s]: ",uname);
|
||||||
|
gets(person);
|
||||||
|
if (!strlen(person)) {
|
||||||
|
bzero(person,sizeof(person));
|
||||||
|
strcpy(person,uname);
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
bad=0;
|
||||||
|
printf("GID [%d]: ",DEFAULT_GROUP);
|
||||||
|
gets(foo);
|
||||||
|
if (!strlen(foo))
|
||||||
|
group=DEFAULT_GROUP;
|
||||||
|
else
|
||||||
|
if (isdigit (*foo)) {
|
||||||
|
group = atoi(foo);
|
||||||
|
if (! (grp = getgrgid (group))) {
|
||||||
|
printf("unknown gid %s\n",foo);
|
||||||
|
group=DEFAULT_GROUP;
|
||||||
|
bad=1;
|
||||||
|
};
|
||||||
|
} else
|
||||||
|
if ((grp = getgrnam (foo)))
|
||||||
|
group = grp->gr_gid;
|
||||||
|
else {
|
||||||
|
printf("unknown group %s\n",foo);
|
||||||
|
group=DEFAULT_GROUP;
|
||||||
|
bad=1;
|
||||||
|
}
|
||||||
|
if (group==0){ /* You're not allowed to make root group users! */
|
||||||
|
printf("Creation of root group users not allowed (must be done by hand)\n");
|
||||||
|
group=DEFAULT_GROUP;
|
||||||
|
bad=1;
|
||||||
|
};
|
||||||
|
} while(bad);
|
||||||
|
|
||||||
|
|
||||||
|
fflush(stdin);
|
||||||
|
|
||||||
|
printf("\nIf home dir ends with a / then [%s] will be appended to it\n",uname);
|
||||||
|
printf("Home Directory [%s/%s]: ",DEFAULT_HOME,uname);
|
||||||
|
fflush(stdout);
|
||||||
|
gets(dir);
|
||||||
|
if (!strlen(dir)) { /* hit return */
|
||||||
|
sprintf(dir,"%s/%s",DEFAULT_HOME,uname);
|
||||||
|
fflush(stdin);
|
||||||
|
} else
|
||||||
|
if (dir[strlen(dir)-1]=='/')
|
||||||
|
sprintf(dir,"%s%s",dir,uname);
|
||||||
|
|
||||||
|
printf("\nShell [%s]: ",DEFAULT_SHELL);
|
||||||
|
fflush(stdout);
|
||||||
|
gets(shell);
|
||||||
|
if (!strlen(shell))
|
||||||
|
sprintf(shell,"%s",DEFAULT_SHELL);
|
||||||
|
|
||||||
|
printf("\nMin. Password Change Days [0]: ");
|
||||||
|
gets(foo);
|
||||||
|
min_pass=atoi(foo);
|
||||||
|
|
||||||
|
printf("Max. Password Change Days [%d]: ",DEFAULT_MAX_PASS);
|
||||||
|
gets(foo);
|
||||||
|
if (strlen(foo) > 1)
|
||||||
|
max_pass = atoi(foo);
|
||||||
|
else
|
||||||
|
max_pass = DEFAULT_MAX_PASS;
|
||||||
|
|
||||||
|
printf("Password Warning Days [%d]: ",DEFAULT_WARN_PASS);
|
||||||
|
gets(foo);
|
||||||
|
warn_pass = atoi(foo);
|
||||||
|
if (warn_pass==0)
|
||||||
|
warn_pass = DEFAULT_WARN_PASS;
|
||||||
|
|
||||||
|
printf("Days after Password Expiry for Account Locking [%d]: ",DEFAULT_USER_DIE);
|
||||||
|
gets(foo);
|
||||||
|
user_die = atoi(foo);
|
||||||
|
if (user_die == 0)
|
||||||
|
user_die = DEFAULT_USER_DIE;
|
||||||
|
|
||||||
|
printf("\nInformation for new user [%s] [%s]:\n",uname,person);
|
||||||
|
printf("Home directory: [%s] Shell: [%s]\n",dir,shell);
|
||||||
|
printf("GID: [%d]\n",group);
|
||||||
|
printf("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n",
|
||||||
|
min_pass,max_pass,warn_pass,user_die);
|
||||||
|
printf("\nIs this correct? [y/N]: ");
|
||||||
|
fflush(stdout);
|
||||||
|
gets(foo);
|
||||||
|
|
||||||
|
done=bad=correct=(foo[0]=='y'||foo[0]=='Y');
|
||||||
|
|
||||||
|
if(bad!=1)
|
||||||
|
printf("\nUser [%s] not added\n",uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(cmd,sizeof(cmd));
|
||||||
|
sprintf(cmd,"%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s",
|
||||||
|
USERADD_PATH,group,dir,shell,person,uname);
|
||||||
|
printf("Calling useradd to add new user:\n%s\n",cmd);
|
||||||
|
if(system(cmd)){
|
||||||
|
printf("User add failed!\n");
|
||||||
|
exit(errno);
|
||||||
|
};
|
||||||
|
bzero(cmd,sizeof(cmd));
|
||||||
|
sprintf(cmd,"%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH,
|
||||||
|
min_pass,max_pass,warn_pass,user_die,uname);
|
||||||
|
printf("%s\n",cmd);
|
||||||
|
if(system(cmd)){
|
||||||
|
printf("There was an error setting password expire values\n");
|
||||||
|
exit(errno);
|
||||||
|
};
|
||||||
|
bzero(cmd,sizeof(cmd));
|
||||||
|
sprintf(cmd,"%s %s",PASSWD_PATH,uname);
|
||||||
|
system(cmd);
|
||||||
|
printf("\nDone.\n");
|
||||||
|
}
|
||||||
|
|
||||||
+4
-4
@@ -34,7 +34,7 @@
|
|||||||
** 1/28/95
|
** 1/28/95
|
||||||
** shadow-adduser 1.3:
|
** shadow-adduser 1.3:
|
||||||
**
|
**
|
||||||
** Basically a bug-fix on my additions in 1.2. Thanks to Terry Stewart
|
** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
|
||||||
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
|
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
|
||||||
** It was such a stupid bug that I would have never seen it myself.
|
** It was such a stupid bug that I would have never seen it myself.
|
||||||
**
|
**
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
** Added in the password date field, which should always reflect the last
|
** Added in the password date field, which should always reflect the last
|
||||||
** date the password was changed, for expiry purposes. "passwd" always
|
** date the password was changed, for expiry purposes. "passwd" always
|
||||||
** updates this field, so the adduser program should set it up right
|
** updates this field, so the adduser program should set it up right
|
||||||
** initially (or a user could keep their initial password forever ;)
|
** initially (or a user could keep thier initial password forever ;)
|
||||||
** The number is in days since Jan 1st, 1970.
|
** The number is in days since Jan 1st, 1970.
|
||||||
**
|
**
|
||||||
** Have fun with it, and someone please make
|
** Have fun with it, and someone please make
|
||||||
@@ -296,7 +296,7 @@ main (void)
|
|||||||
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
|
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
|
||||||
}
|
}
|
||||||
else if (dir[strlen (dir) - 1] == '/')
|
else if (dir[strlen (dir) - 1] == '/')
|
||||||
sprintf (dir+strlen(dir), "%s", usrname);
|
sprintf (dir, "%s%s", dir, usrname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -489,7 +489,7 @@ safeget (char *buf, int maxlen)
|
|||||||
while ((c = getc (stdin)) != EOF && (c != '\n') && (++i < maxlen))
|
while ((c = getc (stdin)) != EOF && (c != '\n') && (++i < maxlen))
|
||||||
{
|
{
|
||||||
bad = (!isalnum (c) && (c != '_') && (c != ' '));
|
bad = (!isalnum (c) && (c != '_') && (c != ' '));
|
||||||
*(buf++) = c;
|
*(buf++) = (char) c;
|
||||||
}
|
}
|
||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ def_home_dir=/home/users
|
|||||||
# default shell
|
# default shell
|
||||||
def_shell=/bin/tcsh
|
def_shell=/bin/tcsh
|
||||||
|
|
||||||
# Default expiration date (mm/dd/yy)
|
# Defaul expiration date (mm/dd/yy)
|
||||||
def_expire=""
|
def_expire=""
|
||||||
|
|
||||||
# default dates
|
# default dates
|
||||||
|
|||||||
+29
-2
@@ -1,7 +1,34 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
#
|
#
|
||||||
# SPDX-FileCopyrightText: 1996 Brian R. Gaeke
|
# Copyright (c) 1996 Brian R. Gaeke
|
||||||
# SPDX-License-Identifier: BSD-4-Clause
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# 3. All advertising materials mentioning features or use of this software
|
||||||
|
# must display the following acknowledgement:
|
||||||
|
# This product includes software developed by Brian R. Gaeke.
|
||||||
|
# 4. The name of the author, Brian R. Gaeke, may not be used to endorse
|
||||||
|
# or promote products derived from this software without specific
|
||||||
|
# prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY BRIAN R. GAEKE ``AS IS'' AND ANY EXPRESS
|
||||||
|
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL BRIAN R. GAEKE BE LIABLE FOR ANY DIRECT,
|
||||||
|
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# Additionally:
|
# Additionally:
|
||||||
#
|
#
|
||||||
|
|||||||
+91
-10
@@ -76,9 +76,36 @@ else
|
|||||||
$echo 'x -' extracting 'Makefile' '(text)'
|
$echo 'x -' extracting 'Makefile' '(text)'
|
||||||
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
|
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
|
||||||
/*
|
/*
|
||||||
# SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
|
# Copyright 2000, International Business Machines, Inc.
|
||||||
# SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
|
# All rights reserved.
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
#
|
||||||
|
# original author: George Kraft IV, gk4@us.ibm.com
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# 3. Neither the name of International Business Machines, Inc., nor the
|
||||||
|
# names of its contributors may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES, INC. AND
|
||||||
|
# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
# INTERNATIONAL BUSINESS MACHINES, INC. OR CONTRIBUTORS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
X
|
X
|
||||||
all: groupmems
|
all: groupmems
|
||||||
@@ -116,9 +143,36 @@ else
|
|||||||
$echo 'x -' extracting 'groupmems.c' '(text)'
|
$echo 'x -' extracting 'groupmems.c' '(text)'
|
||||||
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.c' &&
|
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.c' &&
|
||||||
/*
|
/*
|
||||||
X * SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
|
X * Copyright 2000, International Business Machines, Inc.
|
||||||
X * SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
|
X * All rights reserved.
|
||||||
X * SPDX-License-Identifier: BSD-3-Clause
|
X *
|
||||||
|
X * original author: George Kraft IV, gk4@us.ibm.com
|
||||||
|
X *
|
||||||
|
X * Redistribution and use in source and binary forms, with or without
|
||||||
|
X * modification, are permitted provided that the following conditions
|
||||||
|
X * are met:
|
||||||
|
X *
|
||||||
|
X * 1. Redistributions of source code must retain the above copyright
|
||||||
|
X * notice, this list of conditions and the following disclaimer.
|
||||||
|
X * 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
X * notice, this list of conditions and the following disclaimer in the
|
||||||
|
X * documentation and/or other materials provided with the distribution.
|
||||||
|
X * 3. Neither the name of International Business Machines, Inc., nor the
|
||||||
|
X * names of its contributors may be used to endorse or promote products
|
||||||
|
X * derived from this software without specific prior written permission.
|
||||||
|
X *
|
||||||
|
X * THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES, INC. AND
|
||||||
|
X * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
X * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
X * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
X * INTERNATIONAL BUSINESS MACHINES, INC. OR CONTRIBUTORS BE LIABLE
|
||||||
|
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
X * SUCH DAMAGE.
|
||||||
X */
|
X */
|
||||||
/*
|
/*
|
||||||
**
|
**
|
||||||
@@ -382,9 +436,36 @@ else
|
|||||||
$echo 'x -' extracting 'groupmems.8' '(text)'
|
$echo 'x -' extracting 'groupmems.8' '(text)'
|
||||||
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.8' &&
|
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.8' &&
|
||||||
X.\"
|
X.\"
|
||||||
X.\" SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
|
X.\" Copyright 2000, International Business Machines, Inc.
|
||||||
X.\" SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
|
X.\" All rights reserved.
|
||||||
X.\" SPDX-License-Identifier: BSD-3-Clause
|
X.\"
|
||||||
|
X.\" original author: George Kraft IV, gk4@us.ibm.com
|
||||||
|
X.\"
|
||||||
|
X.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
X.\" modification, are permitted provided that the following conditions
|
||||||
|
X.\" are met:
|
||||||
|
X.\"
|
||||||
|
X.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
X.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
X.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
X.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
X.\" documentation and/or other materials provided with the distribution.
|
||||||
|
X.\" 3. Neither the name of International Business Machines, Inc., nor the
|
||||||
|
X.\" names of its contributors may be used to endorse or promote products
|
||||||
|
X.\" derived from this software without specific prior written permission.
|
||||||
|
X.\"
|
||||||
|
X.\" THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES, INC. AND
|
||||||
|
X.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
X.\" BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
X.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
X.\" INTERNATIONAL BUSINESS MACHINES, INC. OR CONTRIBUTORS BE LIABLE
|
||||||
|
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
X.\" SUCH DAMAGE.
|
||||||
X.\"
|
X.\"
|
||||||
X.\" $Id$
|
X.\" $Id$
|
||||||
X.\"
|
X.\"
|
||||||
@@ -399,7 +480,7 @@ X.B groupmems
|
|||||||
\fB-D\fR |
|
\fB-D\fR |
|
||||||
[\fB-g\fI group_name \fR]
|
[\fB-g\fI group_name \fR]
|
||||||
X.SH DESCRIPTION
|
X.SH DESCRIPTION
|
||||||
The \fBgroupmems\fR utility allows a user to administer their own
|
The \fBgroupmems\fR utility allows a user to administer his/her own
|
||||||
group membership list without the requirement of superuser privileges.
|
group membership list without the requirement of superuser privileges.
|
||||||
The \fBgroupmems\fR utility is for systems that configure its users to
|
The \fBgroupmems\fR utility is for systems that configure its users to
|
||||||
be in their own name sake primary group (i.e., guest / guest).
|
be in their own name sake primary group (i.e., guest / guest).
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
* pwdauth.c - program to verify a given username/password pair.
|
||||||
|
*
|
||||||
|
* Run it with username in argv[1] (may be omitted - default is the
|
||||||
|
* current user), and send it the password over a pipe on stdin.
|
||||||
|
* Exit status: 0 - correct password, 1 - wrong password, >1 - other
|
||||||
|
* errors. For use with shadow passwords, this program should be
|
||||||
|
* installed setuid root.
|
||||||
|
*
|
||||||
|
* This can be used, for example, by xlock - you don't have to install
|
||||||
|
* this large and complex (== possibly insecure) program setuid root,
|
||||||
|
* just modify it to run this simple program to do the authentication.
|
||||||
|
*
|
||||||
|
* Recent versions (xlockmore-3.9) are cleaner, and drop privileges as
|
||||||
|
* soon as possible after getting the user's encrypted password.
|
||||||
|
* Using this program probably doesn't make it more secure, and has one
|
||||||
|
* disadvantage: since we don't get the encrypted user's password at
|
||||||
|
* startup (but at the time the user is authenticated), it is not clear
|
||||||
|
* how we should handle errors (like getpwnam() returning NULL).
|
||||||
|
* - fail the authentication? Problem: no way to unlock (other than kill
|
||||||
|
* the process from somewhere else) if the NIS server stops responding.
|
||||||
|
* - succeed and unlock? Problem: it's too easy to unlock by unplugging
|
||||||
|
* the box from the network and waiting until NIS times out...
|
||||||
|
*
|
||||||
|
* This program is Copyright (C) 1996 Marek Michalkiewicz
|
||||||
|
* <marekm@i17linuxb.ists.pwr.wroc.pl>.
|
||||||
|
*
|
||||||
|
* It may be used and distributed freely for any purposes. There is no
|
||||||
|
* warranty - use at your own risk. I am not liable for any damages etc.
|
||||||
|
* If you improve it, please send me your changes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define USE_SYSLOG to use syslog() to log successful and failed
|
||||||
|
* authentication. This should be safe even if your system has
|
||||||
|
* the infamous syslog buffer overrun security problem...
|
||||||
|
*/
|
||||||
|
#define USE_SYSLOG
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define HAVE_GETSPNAM to get shadow passwords using getspnam().
|
||||||
|
* Some systems don't have getspnam(), but getpwnam() returns
|
||||||
|
* encrypted passwords only if running as root.
|
||||||
|
*
|
||||||
|
* According to the xlock source (not tested, except Linux) -
|
||||||
|
* define: Linux, Solaris 2.x, SVR4, ...
|
||||||
|
* undef: HP-UX with Secured Passwords, FreeBSD, NetBSD, QNX.
|
||||||
|
* Known not supported (yet): Ultrix, OSF/1, SCO.
|
||||||
|
*/
|
||||||
|
#define HAVE_GETSPNAM
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define HAVE_PW_ENCRYPT to use pw_encrypt() instead of crypt().
|
||||||
|
* pw_encrypt() is like the standard crypt(), except that it may
|
||||||
|
* support better password hashing algorithms.
|
||||||
|
*
|
||||||
|
* Define if linking with libshadow.a from the shadow password
|
||||||
|
* suite (Linux, SunOS 4.x?).
|
||||||
|
*/
|
||||||
|
#undef HAVE_PW_ENCRYPT
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define HAVE_AUTH_METHODS to support the shadow suite specific
|
||||||
|
* extension: the encrypted password field contains a list of
|
||||||
|
* administrator defined authentication methods, separated by
|
||||||
|
* semicolons. This program only supports the standard password
|
||||||
|
* authentication method (a string that doesn't start with '@').
|
||||||
|
*/
|
||||||
|
#undef HAVE_AUTH_METHODS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FAIL_DELAY - number of seconds to sleep before exiting if the
|
||||||
|
* password was wrong, to slow down password guessing attempts.
|
||||||
|
*/
|
||||||
|
#define FAIL_DELAY 2
|
||||||
|
|
||||||
|
/* No user-serviceable parts below :-). */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
|
#include <syslog.h>
|
||||||
|
#ifndef LOG_AUTHPRIV
|
||||||
|
#define LOG_AUTHPRIV LOG_AUTH
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
#include <shadow.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PW_ENCRYPT
|
||||||
|
extern char *pw_encrypt();
|
||||||
|
#define crypt pw_encrypt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the password (one line) from fp. We don't turn off echo
|
||||||
|
* because we expect input from a pipe.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
get_line(fp)
|
||||||
|
FILE *fp;
|
||||||
|
{
|
||||||
|
static char buf[128];
|
||||||
|
char *cp;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
cp = buf;
|
||||||
|
while ((ch = getc(fp)) != EOF && ch != '\0' && ch != '\n') {
|
||||||
|
if (cp >= buf + sizeof buf - 1)
|
||||||
|
break;
|
||||||
|
*cp++ = ch;
|
||||||
|
}
|
||||||
|
*cp = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the password file entry for the current user. If the name
|
||||||
|
* returned by getlogin() is correct (matches the current real uid),
|
||||||
|
* return the entry for that user. Otherwise, return the entry (if
|
||||||
|
* any) matching the current real uid. Return NULL on failure.
|
||||||
|
*/
|
||||||
|
static struct passwd *
|
||||||
|
get_my_pwent()
|
||||||
|
{
|
||||||
|
uid_t uid = getuid();
|
||||||
|
char *name = getlogin();
|
||||||
|
|
||||||
|
if (name && *name) {
|
||||||
|
struct passwd *pw = getpwnam(name);
|
||||||
|
|
||||||
|
if (pw && pw->pw_uid == uid)
|
||||||
|
return pw;
|
||||||
|
}
|
||||||
|
return getpwuid(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify the password. The system-dependent shadow support is here.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
password_auth_ok(pw, pass)
|
||||||
|
const struct passwd *pw;
|
||||||
|
const char *pass;
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char *cp;
|
||||||
|
#ifdef HAVE_AUTH_METHODS
|
||||||
|
char *buf;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
struct spwd *sp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pw) {
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
sp = getspnam(pw->pw_name);
|
||||||
|
if (sp)
|
||||||
|
cp = sp->sp_pwdp;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
cp = pw->pw_passwd;
|
||||||
|
} else
|
||||||
|
cp = "xx";
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH_METHODS
|
||||||
|
buf = strdup(cp); /* will be modified by strtok() */
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "Out of memory.\n");
|
||||||
|
exit(13);
|
||||||
|
}
|
||||||
|
cp = strtok(buf, ";");
|
||||||
|
while (cp && *cp == '@')
|
||||||
|
cp = strtok(NULL, ";");
|
||||||
|
|
||||||
|
/* fail if no password authentication for this user */
|
||||||
|
if (!cp)
|
||||||
|
cp = "xx";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (*pass || *cp)
|
||||||
|
result = (strcmp(crypt(pass, cp), cp) == 0);
|
||||||
|
else
|
||||||
|
result = 1; /* user with no password */
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH_METHODS
|
||||||
|
free(buf);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main program.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
struct passwd *pw;
|
||||||
|
char *pass, *name;
|
||||||
|
char myname[32];
|
||||||
|
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
|
openlog("pwdauth", LOG_PID | LOG_CONS, LOG_AUTHPRIV);
|
||||||
|
#endif
|
||||||
|
pw = get_my_pwent();
|
||||||
|
if (!pw) {
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
|
syslog(LOG_ERR, "can't get login name for uid %d.\n",
|
||||||
|
(int) getuid());
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Who are you?\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
strncpy(myname, pw->pw_name, sizeof myname - 1);
|
||||||
|
myname[sizeof myname - 1] = '\0';
|
||||||
|
name = myname;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
name = argv[1];
|
||||||
|
pw = getpwnam(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pass = get_line(stdin);
|
||||||
|
if (password_auth_ok(pw, pass)) {
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
|
syslog(pw->pw_uid ? LOG_INFO : LOG_NOTICE,
|
||||||
|
"user `%s' entered correct password for `%.32s'.\n",
|
||||||
|
myname, name);
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
|
/* be careful not to overrun the syslog buffer */
|
||||||
|
syslog((!pw || pw->pw_uid) ? LOG_NOTICE : LOG_WARNING,
|
||||||
|
"user `%s' entered incorrect password for `%.32s'.\n",
|
||||||
|
myname, name);
|
||||||
|
#endif
|
||||||
|
#ifdef FAIL_DELAY
|
||||||
|
sleep(FAIL_DELAY);
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Wrong password.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* You can use code similar to the following to run this program.
|
||||||
|
* Return values: >=0 - program exit status (use the <sys/wait.h>
|
||||||
|
* macros to get the exit code, it is shifted left by 8 bits),
|
||||||
|
* -1 - check errno.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
verify_password(const char *username, const char *password)
|
||||||
|
{
|
||||||
|
int pipe_fd[2];
|
||||||
|
int pid, wpid, status;
|
||||||
|
|
||||||
|
if (pipe(pipe_fd))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
char *arg[3];
|
||||||
|
char *env[1];
|
||||||
|
|
||||||
|
/* child */
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
if (pipe_fd[0] != 0) {
|
||||||
|
if (dup2(pipe_fd[0], 0) != 0)
|
||||||
|
_exit(127);
|
||||||
|
close(pipe_fd[0]);
|
||||||
|
}
|
||||||
|
arg[0] = "/usr/bin/pwdauth";
|
||||||
|
arg[1] = username;
|
||||||
|
arg[2] = NULL;
|
||||||
|
env[0] = NULL;
|
||||||
|
execve(arg[0], arg, env);
|
||||||
|
_exit(127);
|
||||||
|
} else if (pid == -1) {
|
||||||
|
/* error */
|
||||||
|
close(pipe_fd[0]);
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* parent */
|
||||||
|
close(pipe_fd[0]);
|
||||||
|
write(pipe_fd[1], password, strlen(password));
|
||||||
|
write(pipe_fd[1], "\n", 1);
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
|
||||||
|
while ((wpid = wait(&status)) != pid) {
|
||||||
|
if (wpid == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -2,7 +2,7 @@ Hello Marek,
|
|||||||
|
|
||||||
I have created a diffile against the 980403 release that adds
|
I have created a diffile against the 980403 release that adds
|
||||||
functionality to newusers for automatic handling of users with only
|
functionality to newusers for automatic handling of users with only
|
||||||
anonymous ftp login (using the guestgroup feature in ftpaccess, which
|
anonomous ftp login (using the guestgroup feature in ftpaccess, which
|
||||||
means that the users home directory looks like '/home/user/./'). It also
|
means that the users home directory looks like '/home/user/./'). It also
|
||||||
adds a commandline argument to specify an initial directory structure
|
adds a commandline argument to specify an initial directory structure
|
||||||
for such users, with a tarball normally containing the bin,lib,etc
|
for such users, with a tarball normally containing the bin,lib,etc
|
||||||
|
|||||||
@@ -1311,7 +1311,7 @@
|
|||||||
|
|
||||||
This means that fred's password is valid, it was last changed on
|
This means that fred's password is valid, it was last changed on
|
||||||
03/04/96, it can be changed at any time, it expires after 60 days,
|
03/04/96, it can be changed at any time, it expires after 60 days,
|
||||||
fred will not be warned, and the account won't be disabled when
|
fred will not be warned, and and the account won't be disabled when
|
||||||
the password expires.
|
the password expires.
|
||||||
|
|
||||||
This simply means that if fred logs in after the password expires, he
|
This simply means that if fred logs in after the password expires, he
|
||||||
@@ -1487,7 +1487,7 @@
|
|||||||
|
|
||||||
If a user logs into a line that is listed in /etc/dialups, and his
|
If a user logs into a line that is listed in /etc/dialups, and his
|
||||||
shell is listed in the file /etc/d_passwd he will be allowed access
|
shell is listed in the file /etc/d_passwd he will be allowed access
|
||||||
only by supplying the correct password.
|
only by suppling the correct password.
|
||||||
|
|
||||||
Another useful purpose for using dial-up passwords might be to setup a
|
Another useful purpose for using dial-up passwords might be to setup a
|
||||||
line that only allows a certain type of connect (perhaps a PPP or UUCP
|
line that only allows a certain type of connect (perhaps a PPP or UUCP
|
||||||
|
|||||||
+2
-1
@@ -15,7 +15,7 @@ Changes:
|
|||||||
- code merged into lmain.c --cristiang
|
- code merged into lmain.c --cristiang
|
||||||
|
|
||||||
TODO: - support groups in the limits file
|
TODO: - support groups in the limits file
|
||||||
(only usernames are supported at this moment :-( )
|
(only usernames are supported at this momment :-( )
|
||||||
|
|
||||||
Setting user limits for shadow login program
|
Setting user limits for shadow login program
|
||||||
|
|
||||||
@@ -63,3 +63,4 @@ To completely disable limits for a user, a single dash (-) will do.
|
|||||||
Also, please note that all limit settings are set PER LOGIN. They are
|
Also, please note that all limit settings are set PER LOGIN. They are
|
||||||
not global, nor are they permanent. Perhaps global limits will come, but
|
not global, nor are they permanent. Perhaps global limits will come, but
|
||||||
for now this will have to do ;)
|
for now this will have to do ;)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
# S/Key support
|
|
||||||
shadow-utils can be built with S/Key support using the S/Key package from:
|
|
||||||
* http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libskey/ or
|
|
||||||
* https://gentoo.osuosl.org/distfiles/skey-1.1.5.tar.bz2
|
|
||||||
@@ -26,13 +26,17 @@ New ideas to add to this list are welcome, too. --marekm
|
|||||||
- vipw: check password files for errors after editing
|
- vipw: check password files for errors after editing
|
||||||
- add "maximum time users allowed to stay logged in" limit option to logoutd
|
- add "maximum time users allowed to stay logged in" limit option to logoutd
|
||||||
- handle quotes in /etc/environment like the shell does (but sshd doesn't...)
|
- handle quotes in /etc/environment like the shell does (but sshd doesn't...)
|
||||||
|
- better utmpx support (logoutd, ...)
|
||||||
- better OPIE support (report number of logins left, etc.)
|
- better OPIE support (report number of logins left, etc.)
|
||||||
- new option for /etc/suauth: don't load user's environment (force "su -")
|
- new option for /etc/suauth: don't load user's environment (force "su -")
|
||||||
suggested by Ulisses Alonso Camaro
|
suggested by Ulisses Alonso Camaro
|
||||||
- find out why recent releases won't compile on Solaris
|
- find out why recent releases won't compile on Solaris
|
||||||
|
- newusers UID/GID selection algorithm should be the same as useradd
|
||||||
|
(and use UID_MIN, UID_MAX from login.defs)
|
||||||
- newusers should be able to copy /etc/skel to the new home directory
|
- newusers should be able to copy /etc/skel to the new home directory
|
||||||
(like useradd)
|
(like useradd)
|
||||||
- add directories where other packages can add hooks for package-specific
|
- add directories where other packages can add hooks for package-specific
|
||||||
per-user configuration, to be executed with run-parts. Some hooks should
|
per-user configuration, to be executed with run-parts. Some hooks should
|
||||||
be executed at package install time for existing users, likewise for
|
be executed at package install time for existing users, likewise for
|
||||||
package removal and possibly modification. (Debian Bug#36019)
|
package removal and possibly modification. (Debian Bug#36019)
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
# Build & install
|
|
||||||
|
|
||||||
The following page explains how to build and install the shadow project.
|
|
||||||
Additional information on how to do this in a container environment is provided
|
|
||||||
at the end of the page.
|
|
||||||
|
|
||||||
## Local
|
|
||||||
|
|
||||||
### Dependency installation
|
|
||||||
|
|
||||||
This projects depends on other software packages that need to be installed
|
|
||||||
before building it. We recommend using the dependency installation commands
|
|
||||||
provided by the distributions to install them. Some examples below.
|
|
||||||
|
|
||||||
Debian:
|
|
||||||
```
|
|
||||||
apt-get build-dep shadow
|
|
||||||
```
|
|
||||||
|
|
||||||
Fedora:
|
|
||||||
```
|
|
||||||
dnf builddep shadow-utils
|
|
||||||
```
|
|
||||||
|
|
||||||
An alternative would be to take a look at the CI workflow [file](../../.github/workflows/runner.yml)
|
|
||||||
and get the package names from there. This has the advantage that it
|
|
||||||
also includes new dependencies needed for the development version
|
|
||||||
which might have not been present in the last release.
|
|
||||||
|
|
||||||
### Configure
|
|
||||||
|
|
||||||
The first step is to configure it. You can use the
|
|
||||||
`autogen.sh` script provided by the project. Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
./autogen.sh --without-selinux --enable-man --with-yescrypt
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
The next step is to build the project:
|
|
||||||
|
|
||||||
```
|
|
||||||
make -j4
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install
|
|
||||||
|
|
||||||
The last step is to install it. We recommend avoiding this step and using a
|
|
||||||
disposable system like a VM or a container instead.
|
|
||||||
|
|
||||||
```
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Containers
|
|
||||||
|
|
||||||
Alternatively, you can use any of the preconfigured container images builders
|
|
||||||
to build and install shadow.
|
|
||||||
|
|
||||||
You can either generate a single image by running the following command from
|
|
||||||
the root folder of the project (i.e. Alpine):
|
|
||||||
|
|
||||||
```
|
|
||||||
docker build -f share/containers/alpine.dockerfile . --output build-out/alpine
|
|
||||||
```
|
|
||||||
|
|
||||||
Or generate all of the images with the `container-build.sh` script, as if you
|
|
||||||
were running some of the CI checks locally:
|
|
||||||
|
|
||||||
```
|
|
||||||
share/container-build.sh
|
|
||||||
```
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Continuous Integration (CI)
|
|
||||||
|
|
||||||
Shadow runs a CI workflow every time a pull-request (PR) is updated. This
|
|
||||||
workflow contains several checks to assure the quality of the project, and
|
|
||||||
only pull-requests with green results are merged.
|
|
||||||
|
|
||||||
## Build & install
|
|
||||||
|
|
||||||
The project is built & installed on Ubuntu, Alpine, Debian and Fedora. The last
|
|
||||||
three distributions are built & installed on containers, and the workflow can
|
|
||||||
be triggered locally by following the instructions specified in the
|
|
||||||
[Build & install](build_install.md#containers) page.
|
|
||||||
|
|
||||||
## System tests
|
|
||||||
|
|
||||||
The project is tested on Ubuntu. For that purpose it is built & installed in
|
|
||||||
this distribution in a VM. You can run this step locally by following the
|
|
||||||
instructions provided in the [Tests](tests.md#system-tests) page.
|
|
||||||
|
|
||||||
## Static code analysis
|
|
||||||
|
|
||||||
C and shell static code analysis is also executed. For that purpose
|
|
||||||
[CodeQL](https://codeql.github.com/) and
|
|
||||||
[Differential ShellCheck](https://github.com/marketplace/actions/differential-shellcheck)
|
|
||||||
are used.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Coding style
|
|
||||||
|
|
||||||
* For a general guidance refer to the
|
|
||||||
[Linux kernel coding style](https://www.kernel.org/doc/html/latest/process/coding-style.html)
|
|
||||||
|
|
||||||
* Patches that change the existing coding style are not welcome, as they make
|
|
||||||
downstream porting harder for the distributions
|
|
||||||
|
|
||||||
## Indentation
|
|
||||||
|
|
||||||
Tabs are preferred over spaces for indentation. Loading the `.editorconfig`
|
|
||||||
file in your preferred IDE may help you configure it.
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
## Git and Github
|
|
||||||
|
|
||||||
We recommend you to get familiar with the
|
|
||||||
[git](https://guides.github.com/introduction/git-handbook) and
|
|
||||||
[Github](https://guides.github.com) workflows before posting any changes.
|
|
||||||
|
|
||||||
### Set up in a nut shell
|
|
||||||
|
|
||||||
The following steps describe the process in a nut shell to provide you a basic
|
|
||||||
template:
|
|
||||||
|
|
||||||
* Create an account on [GitHub](https://github.com)
|
|
||||||
* Fork the [shadow repository](https://github.com/shadow-maint/shadow)
|
|
||||||
* Clone the shadow repository
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/shadow-maint/shadow.git
|
|
||||||
```
|
|
||||||
|
|
||||||
* Add your fork as an extra remote
|
|
||||||
|
|
||||||
```
|
|
||||||
git remote add $ghusername git@github.com:$ghusername/shadow.git
|
|
||||||
```
|
|
||||||
|
|
||||||
* Setup your name contact e-mail that you want to use for the development
|
|
||||||
|
|
||||||
```
|
|
||||||
git config user.name "John Smith"
|
|
||||||
git config user.email "john.smith@home.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: this will setup the user information only for this repository. You
|
|
||||||
can also add `--global` switch to the `git config` command to setup these
|
|
||||||
options globally and thus making them available in every git repository.
|
|
||||||
|
|
||||||
* Create a working branch
|
|
||||||
|
|
||||||
```
|
|
||||||
git checkout -b my-changes
|
|
||||||
```
|
|
||||||
|
|
||||||
* Commit changes
|
|
||||||
|
|
||||||
```
|
|
||||||
vim change-what-you-need
|
|
||||||
git commit -s
|
|
||||||
```
|
|
||||||
|
|
||||||
Check
|
|
||||||
[the kernel patches guide](https://www.kernel.org/doc/html/v4.14/process/submitting-patches.html#describe-your-changes)
|
|
||||||
to get an idea on how to write a good commit message.
|
|
||||||
|
|
||||||
* Push your changes to your GitHub repository
|
|
||||||
|
|
||||||
```
|
|
||||||
git push $ghusername my-changes --force
|
|
||||||
```
|
|
||||||
|
|
||||||
* Open a Pull Request against shadow project by clicking on the link provided
|
|
||||||
in the output of the previous step
|
|
||||||
|
|
||||||
* Make sure that all Continuous Integration checks are green and wait review
|
|
||||||
|
|
||||||
## Internal guidelines
|
|
||||||
|
|
||||||
Additionally, you should also check the following internal guidelines to
|
|
||||||
understand the project's development model:
|
|
||||||
|
|
||||||
* [Build & install](build_install.md)
|
|
||||||
* [Coding style](coding_style.md)
|
|
||||||
* [Tests](tests.md)
|
|
||||||
* [Continuous Integration](CI.md)
|
|
||||||
* [Releases](releases.md)
|
|
||||||
* [License](license.md)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# License
|
|
||||||
|
|
||||||
All new source code committed to the shadow project is assumed to be made
|
|
||||||
available under the [BSD-3-Clause](../../COPYING) license unless the submitter
|
|
||||||
specifies another license at that time. The shadow maintainers reserve the
|
|
||||||
right to refuse a submission if the license is deemed incompatible with the
|
|
||||||
goals of the project.
|
|
||||||
|
|
||||||
**Note**: old code may be made available under another license, check the
|
|
||||||
license tag for each file to get additional information.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Releases
|
|
||||||
|
|
||||||
The shadow project doesn't follow any specific timeline to release new software
|
|
||||||
versions. Usually, they are released when a major milestone is finished.
|
|
||||||
|
|
||||||
Released source code, alongside the release notes, are provided in the
|
|
||||||
[release Github page](https://github.com/shadow-maint/shadow/releases).
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Tests
|
|
||||||
|
|
||||||
Currently, shadow only provides system tests.
|
|
||||||
|
|
||||||
## System tests
|
|
||||||
|
|
||||||
These type of tests are written in shell. Unfortunately, the testing framework
|
|
||||||
is tightly coupled to the Ubuntu distribution and it can only be run in this
|
|
||||||
distribution. Besides, if anything fails during the execution the system can
|
|
||||||
be left in an unstable state. Taking that into account you shouldn't run this
|
|
||||||
workflow in your host machine, we recommend to use a disposable system like a
|
|
||||||
VM or a container instead.
|
|
||||||
|
|
||||||
You can execute system tests by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd tests && ./run_all`.
|
|
||||||
```
|
|
||||||
+3
-2
@@ -4,7 +4,8 @@
|
|||||||
sysconf_DATA = login.defs
|
sysconf_DATA = login.defs
|
||||||
|
|
||||||
defaultdir = $(sysconfdir)/default
|
defaultdir = $(sysconfdir)/default
|
||||||
default_DATA =
|
default_DATA = \
|
||||||
|
useradd
|
||||||
|
|
||||||
nonpam_files = \
|
nonpam_files = \
|
||||||
limits \
|
limits \
|
||||||
@@ -20,4 +21,4 @@ EXTRA_DIST = \
|
|||||||
$(sysconf_DATA) \
|
$(sysconf_DATA) \
|
||||||
$(default_DATA)
|
$(default_DATA)
|
||||||
|
|
||||||
SUBDIRS = pam.d shadow-maint
|
SUBDIRS = pam.d
|
||||||
|
|||||||
+46
-155
@@ -6,18 +6,16 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Delay in seconds before being allowed another attempt after a login failure
|
# Delay in seconds before being allowed another attempt after a login failure
|
||||||
# Note: When PAM is used, some modules may enforce a minimum delay (e.g.
|
|
||||||
# pam_unix(8) enforces a 2s delay)
|
|
||||||
#
|
#
|
||||||
FAIL_DELAY 3
|
FAIL_DELAY 3
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable logging and display of /var/log/faillog login(1) failure info.
|
# Enable logging and display of /var/log/faillog login failure info.
|
||||||
#
|
#
|
||||||
FAILLOG_ENAB yes
|
FAILLOG_ENAB yes
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable display of unknown usernames when login(1) failures are recorded.
|
# Enable display of unknown usernames when login failures are recorded.
|
||||||
#
|
#
|
||||||
LOG_UNKFAIL_ENAB no
|
LOG_UNKFAIL_ENAB no
|
||||||
|
|
||||||
@@ -27,19 +25,10 @@ LOG_UNKFAIL_ENAB no
|
|||||||
LOG_OK_LOGINS no
|
LOG_OK_LOGINS no
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable logging and display of /var/log/lastlog login(1) time info.
|
# Enable logging and display of /var/log/lastlog login time info.
|
||||||
#
|
#
|
||||||
LASTLOG_ENAB yes
|
LASTLOG_ENAB yes
|
||||||
|
|
||||||
#
|
|
||||||
# Limit the highest user ID number for which the lastlog entries should
|
|
||||||
# be updated.
|
|
||||||
#
|
|
||||||
# No LASTLOG_UID_MAX means that there is no user ID limit for writing
|
|
||||||
# lastlog entries.
|
|
||||||
#
|
|
||||||
#LASTLOG_UID_MAX
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable checking and display of mailbox status upon login.
|
# Enable checking and display of mailbox status upon login.
|
||||||
#
|
#
|
||||||
@@ -59,13 +48,13 @@ OBSCURE_CHECKS_ENAB yes
|
|||||||
PORTTIME_CHECKS_ENAB yes
|
PORTTIME_CHECKS_ENAB yes
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable setting of ulimit, umask, and niceness from passwd(5) gecos field.
|
# Enable setting of ulimit, umask, and niceness from passwd gecos field.
|
||||||
#
|
#
|
||||||
QUOTAS_ENAB yes
|
QUOTAS_ENAB yes
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable "syslog" logging of su(1) activity - in addition to sulog file logging.
|
# Enable "syslog" logging of su activity - in addition to sulog file logging.
|
||||||
# SYSLOG_SG_ENAB does the same for newgrp(1) and sg(1).
|
# SYSLOG_SG_ENAB does the same for newgrp and sg.
|
||||||
#
|
#
|
||||||
SYSLOG_SU_ENAB yes
|
SYSLOG_SU_ENAB yes
|
||||||
SYSLOG_SG_ENAB yes
|
SYSLOG_SG_ENAB yes
|
||||||
@@ -73,13 +62,13 @@ SYSLOG_SG_ENAB yes
|
|||||||
#
|
#
|
||||||
# If defined, either full pathname of a file containing device names or
|
# If defined, either full pathname of a file containing device names or
|
||||||
# a ":" delimited list of device names. Root logins will be allowed only
|
# a ":" delimited list of device names. Root logins will be allowed only
|
||||||
# from these devices.
|
# upon these devices.
|
||||||
#
|
#
|
||||||
CONSOLE /etc/securetty
|
CONSOLE /etc/securetty
|
||||||
#CONSOLE console:tty01:tty02:tty03:tty04
|
#CONSOLE console:tty01:tty02:tty03:tty04
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, all su(1) activity is logged to this file.
|
# If defined, all su activity is logged to this file.
|
||||||
#
|
#
|
||||||
#SULOG_FILE /var/log/sulog
|
#SULOG_FILE /var/log/sulog
|
||||||
|
|
||||||
@@ -91,33 +80,33 @@ MOTD_FILE /etc/motd
|
|||||||
#MOTD_FILE /etc/motd:/usr/lib/news/news-motd
|
#MOTD_FILE /etc/motd:/usr/lib/news/news-motd
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, this file will be output before each login(1) prompt.
|
# If defined, this file will be output before each login prompt.
|
||||||
#
|
#
|
||||||
#ISSUE_FILE /etc/issue
|
#ISSUE_FILE /etc/issue
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, file which maps tty line to TERM environment parameter.
|
# If defined, file which maps tty line to TERM environment parameter.
|
||||||
# Each line of the file is in a format similar to "vt100 tty01".
|
# Each line of the file is in a format something like "vt100 tty01".
|
||||||
#
|
#
|
||||||
#TTYTYPE_FILE /etc/ttytype
|
#TTYTYPE_FILE /etc/ttytype
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, login(1) failures will be logged here in a utmp format.
|
# If defined, login failures will be logged here in a utmp format.
|
||||||
# last(1), when invoked as lastb(1), will read /var/log/btmp, so...
|
# last, when invoked as lastb, will read /var/log/btmp, so...
|
||||||
#
|
#
|
||||||
FTMP_FILE /var/log/btmp
|
FTMP_FILE /var/log/btmp
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, name of file whose presence will inhibit non-root
|
# If defined, name of file whose presence which will inhibit non-root
|
||||||
# logins. The content of this file should be a message indicating
|
# logins. The contents of this file should be a message indicating
|
||||||
# why logins are inhibited.
|
# why logins are inhibited.
|
||||||
#
|
#
|
||||||
NOLOGINS_FILE /etc/nologin
|
NOLOGINS_FILE /etc/nologin
|
||||||
|
|
||||||
#
|
#
|
||||||
# If defined, the command name to display when running "su -". For
|
# If defined, the command name to display when running "su -". For
|
||||||
# example, if this is defined as "su" then ps(1) will display the
|
# example, if this is defined as "su" then a "ps" will display the
|
||||||
# command as "-su". If not defined, then ps(1) will display the
|
# command is "-su". If not defined, then "ps" would display the
|
||||||
# name of the shell actually being run, e.g. something like "-sh".
|
# name of the shell actually being run, e.g. something like "-sh".
|
||||||
#
|
#
|
||||||
SU_NAME su
|
SU_NAME su
|
||||||
@@ -167,10 +156,10 @@ ENV_PATH PATH=/bin:/usr/bin
|
|||||||
# TTYGROUP Login tty will be assigned this group ownership.
|
# TTYGROUP Login tty will be assigned this group ownership.
|
||||||
# TTYPERM Login tty will be set to this permission.
|
# TTYPERM Login tty will be set to this permission.
|
||||||
#
|
#
|
||||||
# If you have a write(1) program which is "setgid" to a special group
|
# If you have a "write" program which is "setgid" to a special group
|
||||||
# which owns the terminals, define TTYGROUP as the number of such group
|
# which owns the terminals, define TTYGROUP to the group number and
|
||||||
# and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and
|
# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign
|
||||||
# set TTYPERM to either 622 or 600.
|
# TTYPERM to either 622 or 600.
|
||||||
#
|
#
|
||||||
TTYGROUP tty
|
TTYGROUP tty
|
||||||
TTYPERM 0600
|
TTYPERM 0600
|
||||||
@@ -180,6 +169,7 @@ TTYPERM 0600
|
|||||||
#
|
#
|
||||||
# ERASECHAR Terminal ERASE character ('\010' = backspace).
|
# ERASECHAR Terminal ERASE character ('\010' = backspace).
|
||||||
# KILLCHAR Terminal KILL character ('\025' = CTRL/U).
|
# KILLCHAR Terminal KILL character ('\025' = CTRL/U).
|
||||||
|
# UMASK Default "umask" value.
|
||||||
# ULIMIT Default "ulimit" value.
|
# ULIMIT Default "ulimit" value.
|
||||||
#
|
#
|
||||||
# The ERASECHAR and KILLCHAR are used only on System V machines.
|
# The ERASECHAR and KILLCHAR are used only on System V machines.
|
||||||
@@ -190,21 +180,8 @@ TTYPERM 0600
|
|||||||
#
|
#
|
||||||
ERASECHAR 0177
|
ERASECHAR 0177
|
||||||
KILLCHAR 025
|
KILLCHAR 025
|
||||||
#ULIMIT 2097152
|
|
||||||
|
|
||||||
# Default initial "umask" value used by login(1) on non-PAM enabled systems.
|
|
||||||
# Default "umask" value for pam_umask(8) on PAM enabled systems.
|
|
||||||
# UMASK is also used by useradd(8) and newusers(8) to set the mode for new
|
|
||||||
# home directories if HOME_MODE is not set.
|
|
||||||
# 022 is the default value, but 027, or even 077, could be considered
|
|
||||||
# for increased privacy. There is no One True Answer here: each sysadmin
|
|
||||||
# must make up their mind.
|
|
||||||
UMASK 022
|
UMASK 022
|
||||||
|
#ULIMIT 2097152
|
||||||
# HOME_MODE is used by useradd(8) and newusers(8) to set the mode for new
|
|
||||||
# home directories.
|
|
||||||
# If HOME_MODE is not set, the value of UMASK is used to create the mode.
|
|
||||||
#HOME_MODE 0700
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Password aging controls:
|
# Password aging controls:
|
||||||
@@ -228,43 +205,35 @@ PASS_WARN_AGE 7
|
|||||||
SU_WHEEL_ONLY no
|
SU_WHEEL_ONLY no
|
||||||
|
|
||||||
#
|
#
|
||||||
# If compiled with cracklib support, sets the path to the dictionaries
|
# If compiled with cracklib support, where are the dictionaries
|
||||||
#
|
#
|
||||||
CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
|
CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
|
||||||
|
|
||||||
#
|
#
|
||||||
# Min/max values for automatic uid selection in useradd(8)
|
# Min/max values for automatic uid selection in useradd
|
||||||
#
|
#
|
||||||
UID_MIN 1000
|
UID_MIN 1000
|
||||||
UID_MAX 60000
|
UID_MAX 60000
|
||||||
# System accounts
|
# System accounts
|
||||||
SYS_UID_MIN 101
|
SYS_UID_MIN 100
|
||||||
SYS_UID_MAX 999
|
SYS_UID_MAX 999
|
||||||
# Extra per user uids
|
|
||||||
SUB_UID_MIN 100000
|
|
||||||
SUB_UID_MAX 600100000
|
|
||||||
SUB_UID_COUNT 65536
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Min/max values for automatic gid selection in groupadd(8)
|
# Min/max values for automatic gid selection in groupadd
|
||||||
#
|
#
|
||||||
GID_MIN 1000
|
GID_MIN 1000
|
||||||
GID_MAX 60000
|
GID_MAX 60000
|
||||||
# System accounts
|
# System accounts
|
||||||
SYS_GID_MIN 101
|
SYS_GID_MIN 100
|
||||||
SYS_GID_MAX 999
|
SYS_GID_MAX 999
|
||||||
# Extra per user group ids
|
|
||||||
SUB_GID_MIN 100000
|
|
||||||
SUB_GID_MAX 600100000
|
|
||||||
SUB_GID_COUNT 65536
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Max number of login(1) retries if password is bad
|
# Max number of login retries if password is bad
|
||||||
#
|
#
|
||||||
LOGIN_RETRIES 5
|
LOGIN_RETRIES 5
|
||||||
|
|
||||||
#
|
#
|
||||||
# Max time in seconds for login(1)
|
# Max time in seconds for login
|
||||||
#
|
#
|
||||||
LOGIN_TIMEOUT 60
|
LOGIN_TIMEOUT 60
|
||||||
|
|
||||||
@@ -286,12 +255,12 @@ PASS_ALWAYS_WARN yes
|
|||||||
#PASS_MAX_LEN 8
|
#PASS_MAX_LEN 8
|
||||||
|
|
||||||
#
|
#
|
||||||
# Require password before chfn(1)/chsh(1) can make any changes.
|
# Require password before chfn/chsh can make any changes.
|
||||||
#
|
#
|
||||||
CHFN_AUTH yes
|
CHFN_AUTH yes
|
||||||
|
|
||||||
#
|
#
|
||||||
# Which fields may be changed by regular users using chfn(1) - use
|
# Which fields may be changed by regular users using chfn - use
|
||||||
# any combination of letters "frwh" (full name, room number, work
|
# any combination of letters "frwh" (full name, room number, work
|
||||||
# phone, home phone). If not defined, no changes are allowed.
|
# phone, home phone). If not defined, no changes are allowed.
|
||||||
# For backward compatibility, "yes" = "rwh" and "no" = "frwh".
|
# For backward compatibility, "yes" = "rwh" and "no" = "frwh".
|
||||||
@@ -316,19 +285,16 @@ CHFN_RESTRICT rwh
|
|||||||
# Note: If you use PAM, it is recommended to use a value consistent with
|
# Note: If you use PAM, it is recommended to use a value consistent with
|
||||||
# the PAM modules configuration.
|
# the PAM modules configuration.
|
||||||
#
|
#
|
||||||
# This variable is deprecated. You should use ENCRYPT_METHOD instead.
|
# This variable is deprecated. You should use ENCRYPT_METHOD.
|
||||||
#
|
#
|
||||||
#MD5_CRYPT_ENAB no
|
#MD5_CRYPT_ENAB no
|
||||||
|
|
||||||
#
|
#
|
||||||
# Only works if compiled with ENCRYPTMETHOD_SELECT defined:
|
# Only works if compiled with ENCRYPTMETHOD_SELECT defined:
|
||||||
# If set to MD5, MD5-based algorithm will be used for encrypting password
|
# If set to MD5 , MD5-based algorithm will be used for encrypting password
|
||||||
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
|
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
|
||||||
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
|
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
|
||||||
# If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password
|
|
||||||
# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password
|
|
||||||
# If set to DES, DES-based algorithm will be used for encrypting password (default)
|
# If set to DES, DES-based algorithm will be used for encrypting password (default)
|
||||||
# MD5 and DES should not be used for new hashes, see crypt(5) for recommendations.
|
|
||||||
# Overrides the MD5_CRYPT_ENAB option
|
# Overrides the MD5_CRYPT_ENAB option
|
||||||
#
|
#
|
||||||
# Note: If you use PAM, it is recommended to use a value consistent with
|
# Note: If you use PAM, it is recommended to use a value consistent with
|
||||||
@@ -340,72 +306,35 @@ CHFN_RESTRICT rwh
|
|||||||
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
|
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
|
||||||
#
|
#
|
||||||
# Define the number of SHA rounds.
|
# Define the number of SHA rounds.
|
||||||
# With a lot of rounds, it is more difficult to brute-force the password.
|
# With a lot of rounds, it is more difficult to brute forcing the password.
|
||||||
# However, more CPU resources will be needed to authenticate users if
|
# But note also that it more CPU resources will be needed to authenticate
|
||||||
# this value is increased.
|
# users.
|
||||||
#
|
#
|
||||||
# If not specified, the libc will choose the default number of rounds (5000),
|
# If not specified, the libc will choose the default number of rounds (5000).
|
||||||
# which is orders of magnitude too low for modern hardware.
|
# The values must be inside the 1000-999999999 range.
|
||||||
# The values must be within the 1000-999999999 range.
|
|
||||||
# If only one of the MIN or MAX values is set, then this value will be used.
|
# If only one of the MIN or MAX values is set, then this value will be used.
|
||||||
# If MIN > MAX, the highest value will be used.
|
# If MIN > MAX, the highest value will be used.
|
||||||
#
|
#
|
||||||
#SHA_CRYPT_MIN_ROUNDS 5000
|
# SHA_CRYPT_MIN_ROUNDS 5000
|
||||||
#SHA_CRYPT_MAX_ROUNDS 5000
|
# SHA_CRYPT_MAX_ROUNDS 5000
|
||||||
|
|
||||||
#
|
|
||||||
# Only works if ENCRYPT_METHOD is set to BCRYPT.
|
|
||||||
#
|
|
||||||
# Define the number of BCRYPT rounds.
|
|
||||||
# With a lot of rounds, it is more difficult to brute-force the password.
|
|
||||||
# However, more CPU resources will be needed to authenticate users if
|
|
||||||
# this value is increased.
|
|
||||||
#
|
|
||||||
# If not specified, 13 rounds will be attempted.
|
|
||||||
# If only one of the MIN or MAX values is set, then this value will be used.
|
|
||||||
# If MIN > MAX, the highest value will be used.
|
|
||||||
#
|
|
||||||
#BCRYPT_MIN_ROUNDS 13
|
|
||||||
#BCRYPT_MAX_ROUNDS 13
|
|
||||||
|
|
||||||
#
|
|
||||||
# Only works if ENCRYPT_METHOD is set to YESCRYPT.
|
|
||||||
#
|
|
||||||
# Define the YESCRYPT cost factor.
|
|
||||||
# With a higher cost factor, it is more difficult to brute-force the password.
|
|
||||||
# However, more CPU time and more memory will be needed to authenticate users
|
|
||||||
# if this value is increased.
|
|
||||||
#
|
|
||||||
# If not specified, a cost factor of 5 will be used.
|
|
||||||
# The value must be within the 1-11 range.
|
|
||||||
#
|
|
||||||
#YESCRYPT_COST_FACTOR 5
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# List of groups to add to the user's supplementary group set
|
# List of groups to add to the user's supplementary group set
|
||||||
# when logging in from the console (as determined by the CONSOLE
|
# when logging in on the console (as determined by the CONSOLE
|
||||||
# setting). Default is none.
|
# setting). Default is none.
|
||||||
#
|
#
|
||||||
# Use with caution - it is possible for users to gain permanent
|
# Use with caution - it is possible for users to gain permanent
|
||||||
# access to these groups, even when not logged in from the console.
|
# access to these groups, even when not logged in on the console.
|
||||||
# How to do it is left as an exercise for the reader...
|
# How to do it is left as an exercise for the reader...
|
||||||
#
|
#
|
||||||
#CONSOLE_GROUPS floppy:audio:cdrom
|
#CONSOLE_GROUPS floppy:audio:cdrom
|
||||||
|
|
||||||
#
|
#
|
||||||
# Should login be allowed if we can't cd to the home directory?
|
# Should login be allowed if we can't cd to the home directory?
|
||||||
# Default is no.
|
# Default in no.
|
||||||
#
|
#
|
||||||
DEFAULT_HOME yes
|
DEFAULT_HOME yes
|
||||||
|
|
||||||
#
|
|
||||||
# The pwck(8) utility emits a warning for any system account with a home
|
|
||||||
# directory that does not exist. Some system accounts intentionally do
|
|
||||||
# not have a home directory. Such accounts may have this string as
|
|
||||||
# their home directory in /etc/passwd to avoid a spurious warning.
|
|
||||||
#
|
|
||||||
NONEXISTENT /nonexistent
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# If this file exists and is readable, login environment will be
|
# If this file exists and is readable, login environment will be
|
||||||
# read from it. Every line should be in the form name=value.
|
# read from it. Every line should be in the form name=value.
|
||||||
@@ -424,55 +353,17 @@ ENVIRON_FILE /etc/environment
|
|||||||
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
|
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
|
||||||
# the same as gid, and username is the same as the primary group name.
|
# the same as gid, and username is the same as the primary group name.
|
||||||
#
|
#
|
||||||
# This also enables userdel(8) to remove user groups if no members exist.
|
# This also enables userdel to remove user groups if no members exist.
|
||||||
#
|
#
|
||||||
USERGROUPS_ENAB yes
|
USERGROUPS_ENAB yes
|
||||||
|
|
||||||
#
|
#
|
||||||
# If set to a non-zero number, the shadow utilities will make sure that
|
# If set to a non-nul number, the shadow utilities will make sure that
|
||||||
# groups never have more than this number of users on one line.
|
# groups never have more than this number of users on one line.
|
||||||
# This permits to support split groups (groups split into multiple lines,
|
# This permit to support split groups (groups split into multiple lines,
|
||||||
# with the same group ID, to avoid limitation of the line length in the
|
# with the same group ID, to avoid limitation of the line length in the
|
||||||
# group file).
|
# group file).
|
||||||
#
|
#
|
||||||
# 0 is the default value and disables this feature.
|
# 0 is the default value and disables this feature.
|
||||||
#
|
#
|
||||||
#MAX_MEMBERS_PER_GROUP 0
|
#MAX_MEMBERS_PER_GROUP 0
|
||||||
|
|
||||||
#
|
|
||||||
# If useradd(8) should create home directories for users by default (non
|
|
||||||
# system users only).
|
|
||||||
# This option is overridden with the -M or -m flags on the useradd(8)
|
|
||||||
# command-line.
|
|
||||||
#
|
|
||||||
#CREATE_HOME yes
|
|
||||||
|
|
||||||
#
|
|
||||||
# Force use shadow, even if shadow passwd & shadow group files are
|
|
||||||
# missing.
|
|
||||||
#
|
|
||||||
#FORCE_SHADOW yes
|
|
||||||
|
|
||||||
#
|
|
||||||
# Allow newuidmap and newgidmap when running under an alternative
|
|
||||||
# primary group.
|
|
||||||
#
|
|
||||||
#GRANT_AUX_GROUP_SUBIDS yes
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prevents an empty password field to be interpreted as "no authentication
|
|
||||||
# required".
|
|
||||||
# Set to "yes" to prevent for all accounts
|
|
||||||
# Set to "superuser" to prevent for UID 0 / root (default)
|
|
||||||
# Set to "no" to not prevent for any account (dangerous, historical default)
|
|
||||||
PREVENT_NO_AUTH superuser
|
|
||||||
|
|
||||||
#
|
|
||||||
# Select the HMAC cryptography algorithm.
|
|
||||||
# Used in pam_timestamp module to calculate the keyed-hash message
|
|
||||||
# authentication code.
|
|
||||||
#
|
|
||||||
# Note: It is recommended to check hmac(3) to see the possible algorithms
|
|
||||||
# that are available in your system.
|
|
||||||
#
|
|
||||||
#HMAC_CRYPTO_ALGO SHA512
|
|
||||||
|
|||||||
+7
-15
@@ -2,20 +2,19 @@
|
|||||||
# and also cooperate to make a distribution for `make dist'
|
# and also cooperate to make a distribution for `make dist'
|
||||||
|
|
||||||
pamd_files = \
|
pamd_files = \
|
||||||
chfn \
|
|
||||||
chsh \
|
|
||||||
groupmems \
|
|
||||||
login \
|
|
||||||
passwd
|
|
||||||
|
|
||||||
pamd_acct_tools_files = \
|
|
||||||
chage \
|
chage \
|
||||||
|
chfn \
|
||||||
chgpasswd \
|
chgpasswd \
|
||||||
chpasswd \
|
chpasswd \
|
||||||
|
chsh \
|
||||||
groupadd \
|
groupadd \
|
||||||
groupdel \
|
groupdel \
|
||||||
|
groupmems \
|
||||||
groupmod \
|
groupmod \
|
||||||
|
login \
|
||||||
newusers \
|
newusers \
|
||||||
|
passwd \
|
||||||
|
su \
|
||||||
useradd \
|
useradd \
|
||||||
userdel \
|
userdel \
|
||||||
usermod
|
usermod
|
||||||
@@ -23,13 +22,6 @@ pamd_acct_tools_files = \
|
|||||||
if USE_PAM
|
if USE_PAM
|
||||||
pamddir = $(sysconfdir)/pam.d
|
pamddir = $(sysconfdir)/pam.d
|
||||||
pamd_DATA = $(pamd_files)
|
pamd_DATA = $(pamd_files)
|
||||||
if ACCT_TOOLS_SETUID
|
|
||||||
pamd_DATA += $(pamd_acct_tools_files)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if WITH_SU
|
EXTRA_DIST = $(pamd_files)
|
||||||
pamd_files += su
|
|
||||||
endif
|
|
||||||
|
|
||||||
EXTRA_DIST = $(pamd_files) $(pamd_acct_tools_files)
|
|
||||||
|
|||||||
+2
-2
@@ -4,8 +4,8 @@ auth include system-auth
|
|||||||
account required pam_nologin.so
|
account required pam_nologin.so
|
||||||
account include system-auth
|
account include system-auth
|
||||||
password include system-auth
|
password include system-auth
|
||||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
|
session required pam_selinux.so close
|
||||||
session include system-auth
|
session include system-auth
|
||||||
session required pam_loginuid.so
|
session required pam_loginuid.so
|
||||||
session optional pam_console.so
|
session optional pam_console.so
|
||||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
|
session required pam_selinux.so open
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@ auth required pam_wheel.so use_uid
|
|||||||
auth include system-auth
|
auth include system-auth
|
||||||
account include system-auth
|
account include system-auth
|
||||||
password include system-auth
|
password include system-auth
|
||||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
|
session required pam_selinux.so close
|
||||||
session include system-auth
|
session include system-auth
|
||||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
|
session required pam_selinux.so open multiple
|
||||||
session optional pam_xauth.so
|
session optional pam_xauth.so
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
shadowmaint_files = \
|
|
||||||
groupdel-pre.d/01-kill_group_procs.sh \
|
|
||||||
userdel-pre.d/01-kill_user_procs.sh
|
|
||||||
|
|
||||||
EXTRA_DIST = $(shadowmaint_files)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
||||||
GROUPID=`awk -F: '$1 == "'"${SUBJECT}"'" { print $3 }' /etc/group`
|
|
||||||
|
|
||||||
if [ "${GROUPID}" = "" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
for status in /proc/*/status; do
|
|
||||||
# either this isn't a process or its already dead since expanding the list
|
|
||||||
[ -f "$status" ] || continue
|
|
||||||
|
|
||||||
tbuf=${status%/status}
|
|
||||||
pid=${tbuf#/proc/}
|
|
||||||
case "$pid" in
|
|
||||||
"$$") continue;;
|
|
||||||
[0-9]*) :;;
|
|
||||||
*) continue
|
|
||||||
esac
|
|
||||||
|
|
||||||
grep -q '^Groups:.*\b'"${GROUPID}"'\b.*' "/proc/$pid/status" || continue
|
|
||||||
|
|
||||||
kill -9 "$pid" || echo "cannot kill $pid" 1>&2
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
||||||
|
|
||||||
# Check user exists, and if so, send sigkill to processes that the user owns
|
|
||||||
|
|
||||||
ps -eo user >/dev/null 2>&1
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
|
|
||||||
# if the user does not exist, RUNNING will be 0
|
|
||||||
if [ "${RUNNING}x" = "0x" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If there is no ps -eo, traverse the process directly.
|
|
||||||
|
|
||||||
ls -1 /proc | while IFS= read -r PROC; do
|
|
||||||
echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [ -d "/proc/${PROC}" ]; then
|
|
||||||
USR=`stat -c "%U" /proc/${PROC}`
|
|
||||||
if [ "${USR}" = "${SUBJECT}" ]; then
|
|
||||||
echo "Killing ${SUBJECT} owned ${PROC}"
|
|
||||||
kill -9 "${PROC}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# useradd defaults file
|
||||||
|
GROUP=1000
|
||||||
|
HOME=/home
|
||||||
|
INACTIVE=-1
|
||||||
|
EXPIRE=
|
||||||
|
SHELL=/bin/bash
|
||||||
|
SKEL=/etc/skel
|
||||||
|
CREATE_MAIL_SPOOL=yes
|
||||||
+3
-142
@@ -5,181 +5,43 @@ DEFS =
|
|||||||
|
|
||||||
noinst_LTLIBRARIES = libshadow.la
|
noinst_LTLIBRARIES = libshadow.la
|
||||||
|
|
||||||
if USE_PAM
|
libshadow_la_LDFLAGS = -version-info 0:0:0
|
||||||
LIBCRYPT_PAM = $(LIBCRYPT)
|
|
||||||
else
|
|
||||||
LIBCRYPT_PAM =
|
|
||||||
endif
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) $(ECONF_CPPFLAGS)
|
|
||||||
|
|
||||||
libshadow_la_CPPFLAGS = $(ECONF_CPPFLAGS)
|
|
||||||
if HAVE_VENDORDIR
|
|
||||||
libshadow_la_CPPFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
|
|
||||||
endif
|
|
||||||
|
|
||||||
libshadow_la_CPPFLAGS += -I$(top_srcdir)
|
|
||||||
libshadow_la_CFLAGS = $(LIBBSD_CFLAGS) $(LIBCRYPT_PAM) $(LIBSYSTEMD)
|
|
||||||
|
|
||||||
libshadow_la_SOURCES = \
|
libshadow_la_SOURCES = \
|
||||||
addgrps.c \
|
|
||||||
age.c \
|
|
||||||
agetpass.c \
|
|
||||||
alloc.c \
|
|
||||||
alloc.h \
|
|
||||||
audit_help.c \
|
|
||||||
basename.c \
|
|
||||||
bit.c \
|
|
||||||
bit.h \
|
|
||||||
chkname.c \
|
|
||||||
chkname.h \
|
|
||||||
chowndir.c \
|
|
||||||
chowntty.c \
|
|
||||||
cleanup.c \
|
|
||||||
cleanup_group.c \
|
|
||||||
cleanup_user.c \
|
|
||||||
commonio.c \
|
commonio.c \
|
||||||
commonio.h \
|
commonio.h \
|
||||||
console.c \
|
|
||||||
copydir.c \
|
|
||||||
csrand.c \
|
|
||||||
date_to_str.c \
|
|
||||||
defines.h \
|
defines.h \
|
||||||
encrypt.c \
|
encrypt.c \
|
||||||
entry.c \
|
|
||||||
env.c \
|
|
||||||
exitcodes.h \
|
exitcodes.h \
|
||||||
faillog.h \
|
faillog.h \
|
||||||
failure.c \
|
|
||||||
failure.h \
|
|
||||||
fields.c \
|
|
||||||
find_new_gid.c \
|
|
||||||
find_new_uid.c \
|
|
||||||
find_new_sub_gids.c \
|
|
||||||
find_new_sub_uids.c \
|
|
||||||
fputsx.c \
|
fputsx.c \
|
||||||
get_gid.c \
|
|
||||||
get_pid.c \
|
|
||||||
get_uid.c \
|
|
||||||
getdate.h \
|
|
||||||
getdate.y \
|
|
||||||
getdef.c \
|
getdef.c \
|
||||||
getdef.h \
|
getdef.h \
|
||||||
getlong.c \
|
|
||||||
getgr_nam_gid.c \
|
|
||||||
getrange.c \
|
|
||||||
gettime.c \
|
|
||||||
getulong.c \
|
|
||||||
groupio.c \
|
groupio.c \
|
||||||
groupmem.c \
|
groupmem.c \
|
||||||
groupio.h \
|
groupio.h \
|
||||||
gshadow.c \
|
gshadow.c \
|
||||||
hushed.c \
|
|
||||||
idmapping.h \
|
|
||||||
idmapping.c \
|
|
||||||
isexpired.c \
|
|
||||||
limits.c \
|
|
||||||
list.c \
|
|
||||||
lockpw.c \
|
lockpw.c \
|
||||||
loginprompt.c \
|
|
||||||
mail.c \
|
|
||||||
mempcpy.c \
|
|
||||||
mempcpy.h \
|
|
||||||
motd.c \
|
|
||||||
myname.c \
|
|
||||||
nss.c \
|
|
||||||
nscd.c \
|
nscd.c \
|
||||||
nscd.h \
|
nscd.h \
|
||||||
obscure.c \
|
|
||||||
pam_defs.h \
|
pam_defs.h \
|
||||||
pam_pass.c \
|
|
||||||
pam_pass_non_interactive.c \
|
|
||||||
port.c \
|
port.c \
|
||||||
port.h \
|
port.h \
|
||||||
prefix_flag.c \
|
|
||||||
prototypes.h \
|
prototypes.h \
|
||||||
pwauth.c \
|
pwauth.c \
|
||||||
pwauth.h \
|
pwauth.h \
|
||||||
pwio.c \
|
pwio.c \
|
||||||
pwio.h \
|
pwio.h \
|
||||||
pwd_init.c \
|
|
||||||
pwd2spwd.c \
|
|
||||||
pwdcheck.c \
|
|
||||||
pwmem.c \
|
pwmem.c \
|
||||||
remove_tree.c \
|
|
||||||
rlogin.c \
|
|
||||||
root_flag.c \
|
|
||||||
run_part.h \
|
|
||||||
run_part.c \
|
|
||||||
salt.c \
|
|
||||||
selinux.c \
|
|
||||||
semanage.c \
|
|
||||||
setugid.c \
|
|
||||||
setupenv.c \
|
|
||||||
sgetgrent.c \
|
sgetgrent.c \
|
||||||
sgetpwent.c \
|
sgetpwent.c \
|
||||||
sgetspent.c \
|
|
||||||
sgroupio.c \
|
sgroupio.c \
|
||||||
sgroupio.h\
|
sgroupio.h\
|
||||||
shadow.c \
|
shadow.c \
|
||||||
shadowio.c \
|
shadowio.c \
|
||||||
shadowio.h \
|
shadowio.h \
|
||||||
shadowlog.c \
|
|
||||||
shadowlog.h \
|
|
||||||
shadowlog_internal.h \
|
|
||||||
shadowmem.c \
|
shadowmem.c \
|
||||||
shell.c \
|
utent.c
|
||||||
spawn.c \
|
|
||||||
sssd.c \
|
|
||||||
sssd.h \
|
|
||||||
stpecpy.c \
|
|
||||||
stpecpy.h \
|
|
||||||
stpeprintf.c \
|
|
||||||
stpeprintf.h \
|
|
||||||
strtoday.c \
|
|
||||||
sub.c \
|
|
||||||
subordinateio.h \
|
|
||||||
subordinateio.c \
|
|
||||||
sulog.c \
|
|
||||||
ttytype.c \
|
|
||||||
tz.c \
|
|
||||||
ulimit.c \
|
|
||||||
user_busy.c \
|
|
||||||
valid.c \
|
|
||||||
write_full.c \
|
|
||||||
xgetpwnam.c \
|
|
||||||
xprefix_getpwnam.c \
|
|
||||||
xgetpwuid.c \
|
|
||||||
xgetgrnam.c \
|
|
||||||
xgetgrgid.c \
|
|
||||||
xgetspnam.c \
|
|
||||||
yesno.c
|
|
||||||
|
|
||||||
if WITH_TCB
|
|
||||||
libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
|
|
||||||
endif
|
|
||||||
|
|
||||||
if WITH_BTRFS
|
|
||||||
libshadow_la_SOURCES += btrfs.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_LASTLOG
|
|
||||||
libshadow_la_SOURCES += log.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_LOGIND
|
|
||||||
libshadow_la_SOURCES += logind.c
|
|
||||||
else
|
|
||||||
libshadow_la_SOURCES += utmp.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !WITH_LIBBSD
|
|
||||||
libshadow_la_SOURCES += \
|
|
||||||
freezero.h \
|
|
||||||
freezero.c \
|
|
||||||
readpassphrase.h \
|
|
||||||
readpassphrase.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
# These files are unneeded for some reason, listed in
|
# These files are unneeded for some reason, listed in
|
||||||
# order of appearance:
|
# order of appearance:
|
||||||
@@ -188,5 +50,4 @@ endif
|
|||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.indent.pro \
|
.indent.pro \
|
||||||
gshadow_.h \
|
gshadow_.h
|
||||||
xgetXXbyYY.c
|
|
||||||
|
|||||||
-114
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2001 - 2006, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#define SEP ",:"
|
|
||||||
/*
|
|
||||||
* Add groups with names from LIST (separated by commas or colons)
|
|
||||||
* to the supplementary group set. Silently ignore groups which are
|
|
||||||
* already there. Warning: uses strtok().
|
|
||||||
*/
|
|
||||||
int add_groups (const char *list)
|
|
||||||
{
|
|
||||||
GETGROUPS_T *grouplist;
|
|
||||||
size_t i;
|
|
||||||
int ngroups;
|
|
||||||
bool added;
|
|
||||||
char *token;
|
|
||||||
char buf[1024];
|
|
||||||
int ret;
|
|
||||||
FILE *shadow_logfd = log_get_logfd();
|
|
||||||
|
|
||||||
if (strlen (list) >= sizeof (buf)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strcpy (buf, list);
|
|
||||||
|
|
||||||
i = 16;
|
|
||||||
for (;;) {
|
|
||||||
grouplist = MALLOC(i, GETGROUPS_T);
|
|
||||||
if (NULL == grouplist) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ngroups = getgroups (i, grouplist);
|
|
||||||
if ( ( (-1 == ngroups)
|
|
||||||
&& (EINVAL != errno))
|
|
||||||
|| (i > (size_t)ngroups)) {
|
|
||||||
/* Unexpected failure of getgroups or successful
|
|
||||||
* reception of the groups */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* not enough room, so try allocating a larger buffer */
|
|
||||||
free (grouplist);
|
|
||||||
i *= 2;
|
|
||||||
}
|
|
||||||
if (ngroups < 0) {
|
|
||||||
free (grouplist);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
added = false;
|
|
||||||
for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) {
|
|
||||||
struct group *grp;
|
|
||||||
|
|
||||||
grp = getgrnam (token); /* local, no need for xgetgrnam */
|
|
||||||
if (NULL == grp) {
|
|
||||||
fprintf (shadow_logfd, _("Warning: unknown group %s\n"),
|
|
||||||
token);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < (size_t)ngroups && grouplist[i] != grp->gr_gid; i++);
|
|
||||||
|
|
||||||
if (i < (size_t)ngroups) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
|
|
||||||
fputs (_("Warning: too many groups\n"), shadow_logfd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
grouplist = REALLOCF(grouplist, (size_t) ngroups + 1, GETGROUPS_T);
|
|
||||||
if (grouplist == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
grouplist[ngroups] = grp->gr_gid;
|
|
||||||
ngroups++;
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added) {
|
|
||||||
ret = setgroups (ngroups, grouplist);
|
|
||||||
free (grouplist);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
free (grouplist);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else /* HAVE_SETGROUPS && !USE_PAM */
|
|
||||||
extern int ISO_C_forbids_an_empty_translation_unit;
|
|
||||||
#endif /* HAVE_SETGROUPS && !USE_PAM */
|
|
||||||
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2001 - 2006, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include "exitcodes.h"
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <grp.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#ifndef PASSWD_PROGRAM
|
|
||||||
#define PASSWD_PROGRAM "/bin/passwd"
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* expire - force password change if password expired
|
|
||||||
*
|
|
||||||
* expire() calls /bin/passwd to change the user's password
|
|
||||||
* if it has expired.
|
|
||||||
*/
|
|
||||||
int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pid_t child;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if (NULL == sp) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if the user's password has expired, and if so
|
|
||||||
* force them to change their password.
|
|
||||||
*/
|
|
||||||
|
|
||||||
status = isexpired (pw, sp);
|
|
||||||
switch (status) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
(void) fputs (_("Your password has expired."), stdout);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
(void) fputs (_("Your password is inactive."), stdout);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
(void) fputs (_("Your login has expired."), stdout);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setting the maximum valid period to less than the minimum
|
|
||||||
* valid period means that the minimum period will never
|
|
||||||
* occur while the password is valid, so the user can never
|
|
||||||
* change that password.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((status > 1) || (sp->sp_max < sp->sp_min)) {
|
|
||||||
(void) puts (_(" Contact the system administrator."));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
(void) puts (_(" Choose a new password."));
|
|
||||||
(void) fflush (stdout);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close all the files so that unauthorized access won't
|
|
||||||
* occur. This needs to be done anyway because those files
|
|
||||||
* might become stale after "passwd" is executed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
endspent ();
|
|
||||||
endpwent ();
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
endsgent ();
|
|
||||||
#endif
|
|
||||||
endgrent ();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute the /bin/passwd command. The exit status will be
|
|
||||||
* examined to see what the result is. If there are any
|
|
||||||
* errors the routine will exit. This forces the user to
|
|
||||||
* change their password before being able to use the account.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pid = fork ();
|
|
||||||
if (0 == pid) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the UID to be that of the user. This causes
|
|
||||||
* passwd to work just like it would had they executed
|
|
||||||
* it from the command line while logged in.
|
|
||||||
*/
|
|
||||||
#if defined(HAVE_INITGROUPS) && ! defined(USE_PAM)
|
|
||||||
if (setup_uid_gid (pw, false) != 0)
|
|
||||||
#else
|
|
||||||
if (setup_uid_gid (pw) != 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
_exit (126);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) NULL);
|
|
||||||
err = errno;
|
|
||||||
perror ("Can't execute " PASSWD_PROGRAM);
|
|
||||||
_exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
|
|
||||||
} else if ((pid_t) -1 == pid) {
|
|
||||||
perror ("fork");
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (((child = wait (&status)) != pid) && (child != (pid_t)-1));
|
|
||||||
|
|
||||||
if ((child == pid) && (0 == status)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
/*@notreached@*/}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* agecheck - see if warning is needed for password expiration
|
|
||||||
*
|
|
||||||
* agecheck sees how many days until the user's password is going
|
|
||||||
* to expire and warns the user of the pending password expiration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void agecheck (/*@null@*/const struct spwd *sp)
|
|
||||||
{
|
|
||||||
long now = time(NULL) / SCALE;
|
|
||||||
long remain;
|
|
||||||
|
|
||||||
if (NULL == sp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The last, max, and warn fields must be supported or the
|
|
||||||
* warning period cannot be calculated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (-1 == sp->sp_lstchg)
|
|
||||||
|| (-1 == sp->sp_max)
|
|
||||||
|| (-1 == sp->sp_warn)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == sp->sp_lstchg) {
|
|
||||||
(void) puts (_("You must change your password."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
remain = sp->sp_lstchg + sp->sp_max - now;
|
|
||||||
if (remain <= sp->sp_warn) {
|
|
||||||
remain /= DAY / SCALE;
|
|
||||||
if (remain > 1) {
|
|
||||||
(void) printf (_("Your password will expire in %ld days.\n"),
|
|
||||||
remain);
|
|
||||||
} else if (1 == remain) {
|
|
||||||
(void) puts (_("Your password will expire tomorrow."));
|
|
||||||
} else if (remain == 0) {
|
|
||||||
(void) puts (_("Your password will expire today."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-134
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022, Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <readpassphrase.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
#if WITH_LIBBSD == 0
|
|
||||||
#include "freezero.h"
|
|
||||||
#endif /* WITH_LIBBSD */
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(PASS_MAX)
|
|
||||||
#define PASS_MAX BUFSIZ - 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SYNOPSIS
|
|
||||||
* [[gnu::malloc(erase_pass)]]
|
|
||||||
* char *agetpass(const char *prompt);
|
|
||||||
*
|
|
||||||
* void erase_pass(char *pass);
|
|
||||||
*
|
|
||||||
* ARGUMENTS
|
|
||||||
* agetpass()
|
|
||||||
* prompt String to be printed before reading a password.
|
|
||||||
*
|
|
||||||
* erase_pass()
|
|
||||||
* pass password previously returned by agetpass().
|
|
||||||
*
|
|
||||||
* DESCRIPTION
|
|
||||||
* agetpass()
|
|
||||||
* This function is very similar to getpass(3). It has several
|
|
||||||
* advantages compared to getpass(3):
|
|
||||||
*
|
|
||||||
* - Instead of using a static buffer, agetpass() allocates memory
|
|
||||||
* through malloc(3). This makes the function thread-safe, and
|
|
||||||
* also reduces the visibility of the buffer.
|
|
||||||
*
|
|
||||||
* - agetpass() doesn't reallocate internally. Some
|
|
||||||
* implementations of getpass(3), such as glibc, do that, as a
|
|
||||||
* consequence of calling getline(3). That's a bug in glibc,
|
|
||||||
* which allows leaking prefixes of passwords in freed memory.
|
|
||||||
*
|
|
||||||
* - agetpass() doesn't overrun the output buffer. If the input
|
|
||||||
* password is too long, it simply fails. Some implementations
|
|
||||||
* of getpass(3), share the same bug that gets(3) has.
|
|
||||||
*
|
|
||||||
* As soon as possible, the password obtained from agetpass() be
|
|
||||||
* erased by calling erase_pass(), to avoid possibly leaking the
|
|
||||||
* password.
|
|
||||||
*
|
|
||||||
* erase_pass()
|
|
||||||
* This function first clears the password, by calling
|
|
||||||
* explicit_bzero(3) (or an equivalent call), and then frees the
|
|
||||||
* allocated memory by calling free(3).
|
|
||||||
*
|
|
||||||
* NULL is a valid input pointer, and in such a case, this call is
|
|
||||||
* a no-op.
|
|
||||||
*
|
|
||||||
* RETURN VALUE
|
|
||||||
* agetpass() returns a newly allocated buffer containing the
|
|
||||||
* password on success. On error, errno is set to indicate the
|
|
||||||
* error, and NULL is returned.
|
|
||||||
*
|
|
||||||
* ERRORS
|
|
||||||
* agetpass()
|
|
||||||
* This function may fail for any errors that malloc(3) or
|
|
||||||
* readpassphrase(3) may fail, and in addition it may fail for the
|
|
||||||
* following errors:
|
|
||||||
*
|
|
||||||
* ENOBUFS
|
|
||||||
* The input password was longer than PASS_MAX.
|
|
||||||
*
|
|
||||||
* CAVEATS
|
|
||||||
* If a password is passed twice to erase_pass(), the behavior is
|
|
||||||
* undefined.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
agetpass(const char *prompt)
|
|
||||||
{
|
|
||||||
char *pass;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since we want to support passwords upto PASS_MAX, we need
|
|
||||||
* PASS_MAX bytes for the password itself, and one more byte for
|
|
||||||
* the terminating '\0'. We also want to detect truncation, and
|
|
||||||
* readpassphrase(3) doesn't detect it, so we need some trick.
|
|
||||||
* Let's add one more byte, and if the password uses it, it
|
|
||||||
* means the introduced password was longer than PASS_MAX.
|
|
||||||
*/
|
|
||||||
pass = MALLOC(PASS_MAX + 2, char);
|
|
||||||
if (pass == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (readpassphrase(prompt, pass, PASS_MAX + 2, RPP_REQUIRE_TTY) == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
len = strlen(pass);
|
|
||||||
if (len == PASS_MAX + 1) {
|
|
||||||
errno = ENOBUFS;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
freezero(pass, PASS_MAX + 2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
erase_pass(char *pass)
|
|
||||||
{
|
|
||||||
freezero(pass, PASS_MAX + 2);
|
|
||||||
}
|
|
||||||
-73
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2006, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
|
||||||
* SPDX-FileCopyrightText: 2023 , Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Replacements for malloc and strdup with error checking. Too trivial
|
|
||||||
to be worth copyrighting :-). I did that because a lot of code used
|
|
||||||
malloc and strdup without checking for NULL pointer, and I like some
|
|
||||||
message better than a core dump... --marekm
|
|
||||||
|
|
||||||
Yeh, but. Remember that bailing out might leave the system in some
|
|
||||||
bizarre state. You really want to put in error checking, then add
|
|
||||||
some back-out failure recovery code. -- jfh */
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern inline void *xmalloc(size_t size);
|
|
||||||
extern inline void *xmallocarray(size_t nmemb, size_t size);
|
|
||||||
extern inline void *mallocarray(size_t nmemb, size_t size);
|
|
||||||
extern inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
|
|
||||||
extern inline char *xstrdup(const char *str);
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
xcalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
p = calloc(nmemb, size);
|
|
||||||
if (p == NULL)
|
|
||||||
goto x;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
|
|
||||||
x:
|
|
||||||
fprintf(log_get_logfd(), _("%s: %s\n"),
|
|
||||||
log_get_progname(), strerror(errno));
|
|
||||||
exit(13);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
xreallocarray(void *p, size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
p = reallocarrayf(p, nmemb, size);
|
|
||||||
if (p == NULL)
|
|
||||||
goto x;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
|
|
||||||
x:
|
|
||||||
fprintf(log_get_logfd(), _("%s: %s\n"),
|
|
||||||
log_get_progname(), strerror(errno));
|
|
||||||
exit(13);
|
|
||||||
}
|
|
||||||
-115
@@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SHADOW_INCLUDE_LIB_MALLOC_H_
|
|
||||||
#define SHADOW_INCLUDE_LIB_MALLOC_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define CALLOC(n, type) ((type *) calloc(n, sizeof(type)))
|
|
||||||
#define XCALLOC(n, type) ((type *) xcalloc(n, sizeof(type)))
|
|
||||||
#define MALLOC(n, type) ((type *) mallocarray(n, sizeof(type)))
|
|
||||||
#define XMALLOC(n, type) ((type *) xmallocarray(n, sizeof(type)))
|
|
||||||
|
|
||||||
#define REALLOC(ptr, n, type) \
|
|
||||||
({ \
|
|
||||||
__auto_type p_ = (ptr); \
|
|
||||||
\
|
|
||||||
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
|
|
||||||
\
|
|
||||||
(type *) reallocarray(p_, n, sizeof(type)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define REALLOCF(ptr, n, type) \
|
|
||||||
({ \
|
|
||||||
__auto_type p_ = (ptr); \
|
|
||||||
\
|
|
||||||
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
|
|
||||||
\
|
|
||||||
(type *) reallocarrayf(p_, n, sizeof(type)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define XREALLOC(ptr, n, type) \
|
|
||||||
({ \
|
|
||||||
__auto_type p_ = (ptr); \
|
|
||||||
\
|
|
||||||
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
|
|
||||||
\
|
|
||||||
(type *) xreallocarray(p_, n, sizeof(type)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
inline void *xmalloc(size_t size);
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
inline void *xmallocarray(size_t nmemb, size_t size);
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
inline void *mallocarray(size_t nmemb, size_t size);
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
inline char *xstrdup(const char *str);
|
|
||||||
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
void *xcalloc(size_t nmemb, size_t size);
|
|
||||||
ATTR_MALLOC(free)
|
|
||||||
void *xreallocarray(void *p, size_t nmemb, size_t size);
|
|
||||||
|
|
||||||
|
|
||||||
inline void *
|
|
||||||
xmalloc(size_t size)
|
|
||||||
{
|
|
||||||
return xmallocarray(1, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void *
|
|
||||||
xmallocarray(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
return xreallocarray(NULL, nmemb, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void *
|
|
||||||
mallocarray(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
return reallocarray(NULL, nmemb, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void *
|
|
||||||
reallocarrayf(void *p, size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *q;
|
|
||||||
|
|
||||||
q = reallocarray(p, nmemb, size);
|
|
||||||
|
|
||||||
/* realloc(p, 0) is equivalent to free(p); avoid double free. */
|
|
||||||
if (q == NULL && nmemb != 0 && size != 0)
|
|
||||||
free(p);
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline char *
|
|
||||||
xstrdup(const char *str)
|
|
||||||
{
|
|
||||||
return strcpy(XMALLOC(strlen(str) + 1, char), str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // include guard
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2005 , Red Hat, Inc.
|
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Audit helper functions used throughout shadow
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <libaudit.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
int audit_fd;
|
|
||||||
|
|
||||||
void audit_help_open (void)
|
|
||||||
{
|
|
||||||
audit_fd = audit_open ();
|
|
||||||
if (audit_fd < 0) {
|
|
||||||
/* You get these only when the kernel doesn't have
|
|
||||||
* audit compiled in. */
|
|
||||||
if ( (errno == EINVAL)
|
|
||||||
|| (errno == EPROTONOSUPPORT)
|
|
||||||
|| (errno == EAFNOSUPPORT)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(void) fputs (_("Cannot open audit interface - aborting.\n"),
|
|
||||||
log_get_logfd());
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function will log a message to the audit system using a predefined
|
|
||||||
* message format. Parameter usage is as follows:
|
|
||||||
*
|
|
||||||
* type - type of message: AUDIT_USER_CHAUTHTOK for changing any account
|
|
||||||
* attributes.
|
|
||||||
* pgname - program's name
|
|
||||||
* op - operation. "adding user", "changing finger info", "deleting group"
|
|
||||||
* name - user's account or group name. If not available use NULL.
|
|
||||||
* id - uid or gid that the operation is being performed on. This is used
|
|
||||||
* only when user is NULL.
|
|
||||||
*/
|
|
||||||
void audit_logger (int type, unused const char *pgname, const char *op,
|
|
||||||
const char *name, unsigned int id,
|
|
||||||
shadow_audit_result result)
|
|
||||||
{
|
|
||||||
if (audit_fd < 0) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
audit_log_acct_message (audit_fd, type, NULL, op, name, id,
|
|
||||||
NULL, NULL, NULL, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void audit_logger_message (const char *message, shadow_audit_result result)
|
|
||||||
{
|
|
||||||
if (audit_fd < 0) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
audit_log_user_message (audit_fd,
|
|
||||||
AUDIT_USYS_CONFIG,
|
|
||||||
message,
|
|
||||||
NULL, /* hostname */
|
|
||||||
NULL, /* addr */
|
|
||||||
NULL, /* tty */
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* WITH_AUDIT */
|
|
||||||
extern int ISO_C_forbids_an_empty_translation_unit;
|
|
||||||
#endif /* WITH_AUDIT */
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1997, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* basename.c - not worth copyrighting :-). Some versions of Linux libc
|
|
||||||
* already have basename(), other versions don't. To avoid confusion,
|
|
||||||
* we will not use the function from libc and use a different name here.
|
|
||||||
* --marekm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
/*@observer@*/const char *Basename (const char *str)
|
|
||||||
{
|
|
||||||
if (str == NULL) {
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
char *cp = strrchr (str, '/');
|
|
||||||
|
|
||||||
return (NULL != cp) ? cp + 1 : str;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "bit.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
extern inline unsigned long bit_ceilul(unsigned long x);
|
|
||||||
extern inline unsigned long bit_ceil_wrapul(unsigned long x);
|
|
||||||
extern inline int leading_zerosul(unsigned long x);
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SHADOW_INCLUDE_LIB_BIT_H_
|
|
||||||
#define SHADOW_INCLUDE_LIB_BIT_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ULONG_WIDTH
|
|
||||||
#define ULONG_WIDTH (sizeof(unsigned long) * CHAR_BIT)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
inline unsigned long bit_ceilul(unsigned long x);
|
|
||||||
inline unsigned long bit_ceil_wrapul(unsigned long x);
|
|
||||||
inline int leading_zerosul(unsigned long x);
|
|
||||||
|
|
||||||
|
|
||||||
/* stdc_bit_ceilul(3) */
|
|
||||||
inline unsigned long
|
|
||||||
bit_ceilul(unsigned long x)
|
|
||||||
{
|
|
||||||
return 1 + (ULONG_MAX >> leading_zerosul(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* stdc_bit_ceilul(3), but wrap instead of having Undefined Behavior */
|
|
||||||
inline unsigned long
|
|
||||||
bit_ceil_wrapul(unsigned long x)
|
|
||||||
{
|
|
||||||
if (x == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return bit_ceilul(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stdc_leading_zerosul(3) */
|
|
||||||
inline int
|
|
||||||
leading_zerosul(unsigned long x)
|
|
||||||
{
|
|
||||||
return (x == 0) ? ULONG_WIDTH : __builtin_clzl(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // include guard
|
|
||||||
-110
@@ -1,110 +0,0 @@
|
|||||||
#include <linux/btrfs_tree.h>
|
|
||||||
#include <linux/magic.h>
|
|
||||||
#include <sys/statfs.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
static bool path_exists(const char *p)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
return stat(p, &sb) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *btrfs_cmd(void)
|
|
||||||
{
|
|
||||||
const char *const btrfs_paths[] = {"/sbin/btrfs",
|
|
||||||
"/bin/btrfs", "/usr/sbin/btrfs", "/usr/bin/btrfs", NULL};
|
|
||||||
const char *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0, p = btrfs_paths[i]; p; i++, p = btrfs_paths[i])
|
|
||||||
if (path_exists(p))
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const char *arg2)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
const char *cmd = btrfs_cmd();
|
|
||||||
const char *argv[] = {
|
|
||||||
"btrfs",
|
|
||||||
"subvolume",
|
|
||||||
subcmd,
|
|
||||||
arg1,
|
|
||||||
arg2,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!cmd || access(cmd, X_OK)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run_command(cmd, argv, NULL, &status))
|
|
||||||
return -1;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int btrfs_create_subvolume(const char *path)
|
|
||||||
{
|
|
||||||
return run_btrfs_subvolume_cmd("create", path, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int btrfs_remove_subvolume(const char *path)
|
|
||||||
{
|
|
||||||
return run_btrfs_subvolume_cmd("delete", "-C", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adapted from btrfsprogs */
|
|
||||||
/*
|
|
||||||
* This intentionally duplicates btrfs_util_is_subvolume_fd() instead of opening
|
|
||||||
* a file descriptor and calling it, because fstat() and fstatfs() don't accept
|
|
||||||
* file descriptors opened with O_PATH on old kernels (before v3.6 and before
|
|
||||||
* v3.12, respectively), but stat() and statfs() can be called on a path that
|
|
||||||
* the user doesn't have read or write permissions to.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 1 - btrfs subvolume
|
|
||||||
* 0 - not btrfs subvolume
|
|
||||||
* -1 - error
|
|
||||||
*/
|
|
||||||
int btrfs_is_subvolume(const char *path)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = is_btrfs(path);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = stat(path, &st);
|
|
||||||
if (ret == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adapted from btrfsprogs */
|
|
||||||
int is_btrfs(const char *path)
|
|
||||||
{
|
|
||||||
struct statfs sfs;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = statfs(path, &sfs);
|
|
||||||
if (ret == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return sfs.f_type == BTRFS_SUPER_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
-100
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2001 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2005 - 2008, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* is_valid_user_name(), is_valid_group_name() - check the new user/group
|
|
||||||
* name for validity;
|
|
||||||
* return values:
|
|
||||||
* true - OK
|
|
||||||
* false - bad name
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include "defines.h"
|
|
||||||
#include "chkname.h"
|
|
||||||
|
|
||||||
int allow_bad_names = false;
|
|
||||||
|
|
||||||
static bool is_valid_name (const char *name)
|
|
||||||
{
|
|
||||||
if (allow_bad_names) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* User/group names must match gnu e-regex:
|
|
||||||
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?
|
|
||||||
*
|
|
||||||
* as a non-POSIX, extension, allow "$" as the last char for
|
|
||||||
* sake of Samba 3.x "add machine script"
|
|
||||||
*
|
|
||||||
* Also do not allow fully numeric names or just "." or "..".
|
|
||||||
*/
|
|
||||||
int numeric;
|
|
||||||
|
|
||||||
if ('\0' == *name ||
|
|
||||||
('.' == *name && (('.' == name[1] && '\0' == name[2]) ||
|
|
||||||
'\0' == name[1])) ||
|
|
||||||
!((*name >= 'a' && *name <= 'z') ||
|
|
||||||
(*name >= 'A' && *name <= 'Z') ||
|
|
||||||
(*name >= '0' && *name <= '9') ||
|
|
||||||
*name == '_' ||
|
|
||||||
*name == '.')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
numeric = isdigit(*name);
|
|
||||||
|
|
||||||
while ('\0' != *++name) {
|
|
||||||
if (!((*name >= 'a' && *name <= 'z') ||
|
|
||||||
(*name >= 'A' && *name <= 'Z') ||
|
|
||||||
(*name >= '0' && *name <= '9') ||
|
|
||||||
*name == '_' ||
|
|
||||||
*name == '.' ||
|
|
||||||
*name == '-' ||
|
|
||||||
(*name == '$' && name[1] == '\0')
|
|
||||||
)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
numeric &= isdigit(*name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !numeric;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid_user_name (const char *name)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* User names length are limited by the kernel
|
|
||||||
*/
|
|
||||||
if (strlen (name) > sysconf(_SC_LOGIN_NAME_MAX)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_valid_name (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid_group_name (const char *name)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Arbitrary limit for group names.
|
|
||||||
* HP-UX 10 limits to 16 characters
|
|
||||||
*/
|
|
||||||
if ( (GROUP_NAME_MAX_LENGTH > 0)
|
|
||||||
&& (strlen (name) > GROUP_NAME_MAX_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_valid_name (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1997 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* $Id$ */
|
|
||||||
#ifndef _CHKNAME_H_
|
|
||||||
#define _CHKNAME_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* is_valid_user_name(), is_valid_group_name() - check the new user/group
|
|
||||||
* name for validity;
|
|
||||||
* return values:
|
|
||||||
* true - OK
|
|
||||||
* false - bad name
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
extern bool is_valid_user_name (const char *name);
|
|
||||||
extern bool is_valid_group_name (const char *name);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
-146
@@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1992 - 1993, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2010 - , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static int chown_tree_at (int at_fd,
|
|
||||||
const char *path,
|
|
||||||
uid_t old_uid,
|
|
||||||
uid_t new_uid,
|
|
||||||
gid_t old_gid,
|
|
||||||
gid_t new_gid)
|
|
||||||
{
|
|
||||||
DIR *dir;
|
|
||||||
const struct dirent *ent;
|
|
||||||
struct stat dir_sb;
|
|
||||||
int dir_fd, rc = 0;
|
|
||||||
|
|
||||||
dir_fd = openat (at_fd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
|
|
||||||
if (dir_fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = fdopendir (dir_fd);
|
|
||||||
if (!dir) {
|
|
||||||
(void) close (dir_fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the directory and read each entry. Every entry is tested
|
|
||||||
* to see if it is a directory, and if so this routine is called
|
|
||||||
* recursively. If not, it is checked to see if an ownership
|
|
||||||
* shall be changed.
|
|
||||||
*/
|
|
||||||
while ((ent = readdir (dir))) {
|
|
||||||
uid_t tmpuid = (uid_t) -1;
|
|
||||||
gid_t tmpgid = (gid_t) -1;
|
|
||||||
struct stat ent_sb;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip the "." and ".." entries
|
|
||||||
*/
|
|
||||||
if ( (strcmp (ent->d_name, ".") == 0)
|
|
||||||
|| (strcmp (ent->d_name, "..") == 0)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = fstatat (dirfd(dir), ent->d_name, &ent_sb, AT_SYMLINK_NOFOLLOW);
|
|
||||||
if (rc < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR (ent_sb.st_mode)) {
|
|
||||||
/*
|
|
||||||
* Do the entire subdirectory.
|
|
||||||
*/
|
|
||||||
rc = chown_tree_at (dirfd(dir), ent->d_name, old_uid, new_uid, old_gid, new_gid);
|
|
||||||
if (0 != rc) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* By default, the IDs are not changed (-1).
|
|
||||||
*
|
|
||||||
* If the file is not owned by the user, the owner is not
|
|
||||||
* changed.
|
|
||||||
*
|
|
||||||
* If the file is not group-owned by the group, the
|
|
||||||
* group-owner is not changed.
|
|
||||||
*/
|
|
||||||
if (((uid_t) -1 == old_uid) || (ent_sb.st_uid == old_uid)) {
|
|
||||||
tmpuid = new_uid;
|
|
||||||
}
|
|
||||||
if (((gid_t) -1 == old_gid) || (ent_sb.st_gid == old_gid)) {
|
|
||||||
tmpgid = new_gid;
|
|
||||||
}
|
|
||||||
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
|
||||||
rc = fchownat (dirfd(dir), ent->d_name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
|
|
||||||
if (0 != rc) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now do the root of the tree
|
|
||||||
*/
|
|
||||||
if ((0 == rc) && (fstat (dirfd(dir), &dir_sb) == 0)) {
|
|
||||||
uid_t tmpuid = (uid_t) -1;
|
|
||||||
gid_t tmpgid = (gid_t) -1;
|
|
||||||
if (((uid_t) -1 == old_uid) || (dir_sb.st_uid == old_uid)) {
|
|
||||||
tmpuid = new_uid;
|
|
||||||
}
|
|
||||||
if (((gid_t) -1 == old_gid) || (dir_sb.st_gid == old_gid)) {
|
|
||||||
tmpgid = new_gid;
|
|
||||||
}
|
|
||||||
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
|
||||||
rc = fchown (dirfd(dir), tmpuid, tmpgid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rc = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) closedir (dir);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* chown_tree - change ownership of files in a directory tree
|
|
||||||
*
|
|
||||||
* chown_dir() walks a directory tree and changes the ownership
|
|
||||||
* of all files owned by the provided user ID.
|
|
||||||
*
|
|
||||||
* Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
|
|
||||||
* will have their ownership (resp. group-ownership) modified, unless
|
|
||||||
* old_uid (resp. old_gid) is set to -1.
|
|
||||||
*
|
|
||||||
* new_uid and new_gid can be set to -1 to indicate that no owner or
|
|
||||||
* group-owner shall be changed.
|
|
||||||
*/
|
|
||||||
int chown_tree (const char *root,
|
|
||||||
uid_t old_uid,
|
|
||||||
uid_t new_uid,
|
|
||||||
gid_t old_gid,
|
|
||||||
gid_t new_gid)
|
|
||||||
{
|
|
||||||
return chown_tree_at (AT_FDCWD, root, old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2001, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include <pwd.h>
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* chown_tty() sets the login tty to be owned by the new user ID
|
|
||||||
* with TTYPERM modes
|
|
||||||
*/
|
|
||||||
|
|
||||||
void chown_tty (const struct passwd *info)
|
|
||||||
{
|
|
||||||
struct group *grent;
|
|
||||||
gid_t gid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if login.defs has some value configured for the port group
|
|
||||||
* ID. Otherwise, use the user's primary group ID.
|
|
||||||
*/
|
|
||||||
|
|
||||||
grent = getgr_nam_gid (getdef_str ("TTYGROUP"));
|
|
||||||
if (NULL != grent) {
|
|
||||||
gid = grent->gr_gid;
|
|
||||||
gr_free (grent);
|
|
||||||
} else {
|
|
||||||
gid = info->pw_gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Change the permissions on the TTY to be owned by the user with
|
|
||||||
* the group as determined above.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|
|
||||||
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
|
|
||||||
int err = errno;
|
|
||||||
FILE *shadow_logfd = log_get_logfd();
|
|
||||||
|
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("Unable to change owner or mode of tty stdin: %s"),
|
|
||||||
strerror (err));
|
|
||||||
SYSLOG ((LOG_WARN,
|
|
||||||
"unable to change owner or mode of tty stdin for user `%s': %s\n",
|
|
||||||
info->pw_name, strerror (err)));
|
|
||||||
if (EROFS != err) {
|
|
||||||
closelog ();
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef __linux__
|
|
||||||
/*
|
|
||||||
* Please don't add code to chown /dev/vcs* to the user logging in -
|
|
||||||
* it's a potential security hole. I wouldn't like the previous user
|
|
||||||
* to hold the file descriptor open and watch my screen. We don't
|
|
||||||
* have the *BSD revoke() system call yet, and vhangup() only works
|
|
||||||
* for tty devices (which vcs* is not). --marekm
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
-121
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2011, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The cleanup_functions stack.
|
|
||||||
*/
|
|
||||||
#define CLEANUP_FUNCTIONS 10
|
|
||||||
|
|
||||||
typedef /*@null@*/void * parg_t;
|
|
||||||
|
|
||||||
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
|
|
||||||
static parg_t cleanup_function_args[CLEANUP_FUNCTIONS];
|
|
||||||
static pid_t cleanup_pid = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* - Cleanup functions shall not fail.
|
|
||||||
* - You should register do_cleanups with atexit.
|
|
||||||
* - You should add cleanup functions to the stack with add_cleanup when
|
|
||||||
* an operation is expected to be executed later, and remove it from the
|
|
||||||
* stack with del_cleanup when it has been executed.
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* do_cleanups - perform the actions stored in the cleanup_functions stack.
|
|
||||||
*
|
|
||||||
* Cleanup action are not executed on exit of the processes started by the
|
|
||||||
* parent (first caller of add_cleanup).
|
|
||||||
*
|
|
||||||
* It is intended to be used as:
|
|
||||||
* atexit (do_cleanups);
|
|
||||||
*/
|
|
||||||
void do_cleanups (void)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Make sure there were no overflow */
|
|
||||||
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
|
|
||||||
|
|
||||||
if (getpid () != cleanup_pid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = CLEANUP_FUNCTIONS;
|
|
||||||
do {
|
|
||||||
i--;
|
|
||||||
if (cleanup_functions[i] != NULL) {
|
|
||||||
cleanup_functions[i] (cleanup_function_args[i]);
|
|
||||||
}
|
|
||||||
} while (i>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* add_cleanup - Add a cleanup_function to the cleanup_functions stack.
|
|
||||||
*/
|
|
||||||
void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
assert (NULL != pcf);
|
|
||||||
|
|
||||||
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
|
|
||||||
|
|
||||||
if (0 == cleanup_pid) {
|
|
||||||
cleanup_pid = getpid ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the cleanup_function at the end of the stack */
|
|
||||||
for (i=0; NULL != cleanup_functions[i]; i++);
|
|
||||||
cleanup_functions[i] = pcf;
|
|
||||||
cleanup_function_args[i] = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
|
|
||||||
*/
|
|
||||||
void del_cleanup (/*@notnull@*/cleanup_function pcf)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
assert (NULL != pcf);
|
|
||||||
|
|
||||||
/* Find the pcf cleanup function */
|
|
||||||
for (i=0; i<CLEANUP_FUNCTIONS; i++) {
|
|
||||||
if (cleanup_functions[i] == pcf) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the cleanup function was found */
|
|
||||||
assert (i<CLEANUP_FUNCTIONS);
|
|
||||||
|
|
||||||
/* Move the rest of the cleanup functions */
|
|
||||||
for (; i<CLEANUP_FUNCTIONS; i++) {
|
|
||||||
/* Make sure the cleanup function was specified only once */
|
|
||||||
assert ( (i == (CLEANUP_FUNCTIONS -1))
|
|
||||||
|| (cleanup_functions[i+1] != pcf));
|
|
||||||
|
|
||||||
if (i == (CLEANUP_FUNCTIONS -1)) {
|
|
||||||
cleanup_functions[i] = NULL;
|
|
||||||
cleanup_function_args[i] = NULL;
|
|
||||||
} else {
|
|
||||||
cleanup_functions[i] = cleanup_functions[i+1];
|
|
||||||
cleanup_function_args[i] = cleanup_function_args[i+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A NULL indicates the end of the stack */
|
|
||||||
if (NULL == cleanup_functions[i]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "groupio.h"
|
|
||||||
#include "sgroupio.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_group - Report failure to add a group to the system
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a group to the system.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_group (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add group %s", name));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
|
||||||
"",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_del_group - Report failure to remove a group from the system
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to remove a group from the system.
|
|
||||||
*/
|
|
||||||
void cleanup_report_del_group (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, log_get_progname(),
|
|
||||||
"",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanup_report_mod_group (void *cleanup_info)
|
|
||||||
{
|
|
||||||
const struct cleanup_info_mod *info;
|
|
||||||
info = (const struct cleanup_info_mod *)cleanup_info;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"failed to change %s (%s)",
|
|
||||||
gr_dbname (),
|
|
||||||
info->action));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_ACCT, log_get_progname(),
|
|
||||||
info->audit_msg,
|
|
||||||
info->name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
void cleanup_report_mod_gshadow (void *cleanup_info)
|
|
||||||
{
|
|
||||||
const struct cleanup_info_mod *info;
|
|
||||||
info = (const struct cleanup_info_mod *)cleanup_info;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"failed to change %s (%s)",
|
|
||||||
sgr_dbname (),
|
|
||||||
info->action));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_ACCT, log_get_progname(),
|
|
||||||
info->audit_msg,
|
|
||||||
info->name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_group_group - Report failure to add a group to group
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a group to the
|
|
||||||
* group database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_group_group (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
|
||||||
"adding group to /etc/group",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_group_gshadow - Report failure to add a group to gshadow
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a group to the
|
|
||||||
* gshadow database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_group_gshadow (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
|
||||||
"adding group to /etc/gshadow",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_del_group_group - Report failure to remove a group from the
|
|
||||||
* regular group database
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to remove a group from the
|
|
||||||
* regular group database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_del_group_group (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"failed to remove group %s from %s",
|
|
||||||
name, gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
|
||||||
"removing group from /etc/group",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
/*
|
|
||||||
* cleanup_report_del_group_gshadow - Report failure to remove a group from
|
|
||||||
* gshadow
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to remove a group from the
|
|
||||||
* gshadow database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_del_group_gshadow (void *group_name)
|
|
||||||
{
|
|
||||||
const char *name = group_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"failed to remove group %s from %s",
|
|
||||||
name, sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
|
||||||
"removing group from /etc/gshadow",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_unlock_group - Unlock the group file
|
|
||||||
*
|
|
||||||
* It should be registered after the group file is successfully locked.
|
|
||||||
*/
|
|
||||||
void cleanup_unlock_group (unused void *arg)
|
|
||||||
{
|
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to unlock %s\n"),
|
|
||||||
log_get_progname(), gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger_message ("unlocking group file",
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
/*
|
|
||||||
* cleanup_unlock_gshadow - Unlock the gshadow file
|
|
||||||
*
|
|
||||||
* It should be registered after the gshadow file is successfully locked.
|
|
||||||
*/
|
|
||||||
void cleanup_unlock_gshadow (unused void *arg)
|
|
||||||
{
|
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to unlock %s\n"),
|
|
||||||
log_get_progname(), sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger_message ("unlocking gshadow file",
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "pwio.h"
|
|
||||||
#include "shadowio.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_user - Report failure to add a user to the system
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a user to the system.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_user (void *user_name)
|
|
||||||
{
|
|
||||||
const char *name = user_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add user %s", name));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_USER, log_get_progname(),
|
|
||||||
"",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanup_report_mod_passwd (void *cleanup_info)
|
|
||||||
{
|
|
||||||
const struct cleanup_info_mod *info;
|
|
||||||
info = (const struct cleanup_info_mod *)cleanup_info;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"failed to change %s (%s)",
|
|
||||||
pw_dbname (),
|
|
||||||
info->action));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_ACCT, log_get_progname(),
|
|
||||||
info->audit_msg,
|
|
||||||
info->name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_user_passwd - Report failure to add a user to
|
|
||||||
* /etc/passwd
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a user to the
|
|
||||||
* /etc/passwd database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_user_passwd (void *user_name)
|
|
||||||
{
|
|
||||||
const char *name = user_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_USER, log_get_progname(),
|
|
||||||
"adding user to /etc/passwd",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_report_add_user_shadow - Report failure to add a user to
|
|
||||||
* /etc/shadow
|
|
||||||
*
|
|
||||||
* It should be registered when it is decided to add a user to the
|
|
||||||
* /etc/shadow database.
|
|
||||||
*/
|
|
||||||
void cleanup_report_add_user_shadow (void *user_name)
|
|
||||||
{
|
|
||||||
const char *name = user_name;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_USER, log_get_progname(),
|
|
||||||
"adding user to /etc/shadow",
|
|
||||||
name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_unlock_passwd - Unlock the /etc/passwd database
|
|
||||||
*
|
|
||||||
* It should be registered after the passwd database is successfully locked.
|
|
||||||
*/
|
|
||||||
void cleanup_unlock_passwd (unused void *arg)
|
|
||||||
{
|
|
||||||
if (pw_unlock () == 0) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to unlock %s\n"),
|
|
||||||
log_get_progname(), pw_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger_message ("unlocking passwd file",
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cleanup_unlock_shadow - Unlock the /etc/shadow database
|
|
||||||
*
|
|
||||||
* It should be registered after the shadow database is successfully locked.
|
|
||||||
*/
|
|
||||||
void cleanup_unlock_shadow (unused void *arg)
|
|
||||||
{
|
|
||||||
if (spw_unlock () == 0) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to unlock %s\n"),
|
|
||||||
log_get_progname(), spw_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger_message ("unlocking shadow file",
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+321
-581
File diff suppressed because it is too large
Load Diff
+57
-47
@@ -1,27 +1,50 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2001 - 2005, Tomasz Kłoczko
|
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
|
||||||
* SPDX-FileCopyrightText: 2007 - 2010, Nicolas François
|
* Copyright (c) 2007 - 2008, Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
#ifndef COMMONIO_H
|
#ifndef _COMMONIO_H
|
||||||
#define COMMONIO_H
|
#define _COMMONIO_H
|
||||||
|
|
||||||
#include "defines.h" /* bool */
|
|
||||||
|
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
#include <selinux/selinux.h>
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Linked list entry.
|
* Linked list entry.
|
||||||
*/
|
*/
|
||||||
struct commonio_entry {
|
struct commonio_entry {
|
||||||
/*@null@*/char *line;
|
char *line;
|
||||||
/*@null@*/void *eptr; /* struct passwd, struct spwd, ... */
|
void *eptr; /* struct passwd, struct spwd, ... */
|
||||||
/*@dependent@*/ /*@null@*/struct commonio_entry *prev;
|
struct commonio_entry *prev, *next;
|
||||||
/*@owned@*/ /*@null@*/struct commonio_entry *next;
|
unsigned int changed:1;
|
||||||
bool changed:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -32,12 +55,12 @@ struct commonio_ops {
|
|||||||
* Make a copy of the object (for example, struct passwd)
|
* Make a copy of the object (for example, struct passwd)
|
||||||
* and all strings pointed by it, in malloced memory.
|
* and all strings pointed by it, in malloced memory.
|
||||||
*/
|
*/
|
||||||
/*@null@*/ /*@only@*/void *(*dup) (const void *);
|
void *(*dup) (const void *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* free() the object including any strings pointed by it.
|
* free() the object including any strings pointed by it.
|
||||||
*/
|
*/
|
||||||
void (*free) (/*@out@*/ /*@only@*/void *);
|
void (*free) (void *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the name of the object (for example, pw_name
|
* Return the name of the object (for example, pw_name
|
||||||
@@ -61,7 +84,7 @@ struct commonio_ops {
|
|||||||
* fgets and fputs (can be replaced by versions that
|
* fgets and fputs (can be replaced by versions that
|
||||||
* understand line continuation conventions).
|
* understand line continuation conventions).
|
||||||
*/
|
*/
|
||||||
/*@null@*/char *(*fgets) (/*@returned@*/ /*@out@*/char *s, int n, FILE *stream);
|
char *(*fgets) (char *, int, FILE *);
|
||||||
int (*fputs) (const char *, FILE *);
|
int (*fputs) (const char *, FILE *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -70,8 +93,8 @@ struct commonio_ops {
|
|||||||
* is open or before it is closed.
|
* is open or before it is closed.
|
||||||
* They return 0 on failure and 1 on success.
|
* They return 0 on failure and 1 on success.
|
||||||
*/
|
*/
|
||||||
/*@null@*/int (*open_hook) (void);
|
int (*open_hook) (void);
|
||||||
/*@null@*/int (*close_hook) (void);
|
int (*close_hook) (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -86,60 +109,47 @@ struct commonio_db {
|
|||||||
/*
|
/*
|
||||||
* Operations from above.
|
* Operations from above.
|
||||||
*/
|
*/
|
||||||
/*@observer@*/const struct commonio_ops *ops;
|
struct commonio_ops *ops;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Currently open file stream.
|
* Currently open file stream.
|
||||||
*/
|
*/
|
||||||
/*@dependent@*/ /*@null@*/FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
#ifdef WITH_SELINUX
|
||||||
/*@null@*/char *scontext;
|
security_context_t scontext;
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
* Default permissions and owner for newly created data file.
|
|
||||||
*/
|
|
||||||
mode_t st_mode;
|
|
||||||
uid_t st_uid;
|
|
||||||
gid_t st_gid;
|
|
||||||
/*
|
/*
|
||||||
* Head, tail, current position in linked list.
|
* Head, tail, current position in linked list.
|
||||||
*/
|
*/
|
||||||
/*@owned@*/ /*@null@*/struct commonio_entry *head;
|
struct commonio_entry *head, *tail, *cursor;
|
||||||
/*@dependent@*/ /*@null@*/struct commonio_entry *tail;
|
|
||||||
/*@dependent@*/ /*@null@*/struct commonio_entry *cursor;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Various flags.
|
* Various flags.
|
||||||
*/
|
*/
|
||||||
bool changed:1;
|
unsigned int changed:1;
|
||||||
bool isopen:1;
|
unsigned int isopen:1;
|
||||||
bool locked:1;
|
unsigned int locked:1;
|
||||||
bool readonly:1;
|
unsigned int readonly:1;
|
||||||
bool setname:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int commonio_setname (struct commonio_db *, const char *);
|
extern int commonio_setname (struct commonio_db *, const char *);
|
||||||
extern bool commonio_present (const struct commonio_db *db);
|
extern int commonio_present (const struct commonio_db *);
|
||||||
extern int commonio_lock (struct commonio_db *);
|
extern int commonio_lock (struct commonio_db *);
|
||||||
extern int commonio_lock_nowait (struct commonio_db *, bool log);
|
extern int commonio_lock_nowait (struct commonio_db *);
|
||||||
extern int do_fcntl_lock (const char *file, bool log, short type);
|
|
||||||
extern int commonio_open (struct commonio_db *, int);
|
extern int commonio_open (struct commonio_db *, int);
|
||||||
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
|
extern const void *commonio_locate (struct commonio_db *, const char *);
|
||||||
extern int commonio_update (struct commonio_db *, const void *);
|
extern int commonio_update (struct commonio_db *, const void *);
|
||||||
#ifdef ENABLE_SUBIDS
|
|
||||||
extern int commonio_append (struct commonio_db *, const void *);
|
|
||||||
#endif /* ENABLE_SUBIDS */
|
|
||||||
extern int commonio_remove (struct commonio_db *, const char *);
|
extern int commonio_remove (struct commonio_db *, const char *);
|
||||||
extern int commonio_rewind (struct commonio_db *);
|
extern int commonio_rewind (struct commonio_db *);
|
||||||
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
|
extern const void *commonio_next (struct commonio_db *);
|
||||||
extern int commonio_close (struct commonio_db *);
|
extern int commonio_close (struct commonio_db *);
|
||||||
extern int commonio_unlock (struct commonio_db *);
|
extern int commonio_unlock (struct commonio_db *);
|
||||||
extern void commonio_del_entry (struct commonio_db *,
|
extern void commonio_del_entry (struct commonio_db *,
|
||||||
const struct commonio_entry *);
|
const struct commonio_entry *);
|
||||||
extern int commonio_sort_wrt (struct commonio_db *shadow,
|
extern int commonio_sort_wrt (struct commonio_db *shadow,
|
||||||
const struct commonio_db *passwd);
|
struct commonio_db *passwd);
|
||||||
extern int commonio_sort (struct commonio_db *db,
|
extern int commonio_sort (struct commonio_db *db,
|
||||||
int (*cmp) (const void *, const void *));
|
int (*cmp) (const void *, const void *));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
-108
@@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1991 , Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1991 , Chip Rosenthal
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2010, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include "defines.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is now rather generic function which decides if "tty" is listed
|
|
||||||
* under "cfgin" in config (directly or indirectly). Fallback to default if
|
|
||||||
* something is bad.
|
|
||||||
*/
|
|
||||||
static bool is_listed (const char *cfgin, const char *tty, bool def)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char buf[1024], *s;
|
|
||||||
const char *cons;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the CONSOLE configuration definition isn't given,
|
|
||||||
* fallback to default.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cons = getdef_str (cfgin);
|
|
||||||
if (NULL == cons) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this isn't a filename, then it is a ":" delimited list of
|
|
||||||
* console devices upon which root logins are allowed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (*cons != '/') {
|
|
||||||
char *pbuf;
|
|
||||||
strlcpy (buf, cons, sizeof (buf));
|
|
||||||
pbuf = &buf[0];
|
|
||||||
while ((s = strtok (pbuf, ":")) != NULL) {
|
|
||||||
if (strcmp (s, tty) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbuf = NULL;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we can't open the console list, then call everything a
|
|
||||||
* console - otherwise root will never be allowed to login.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fp = fopen (cons, "r");
|
|
||||||
if (NULL == fp) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if this tty is listed in the console file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (fgets (buf, sizeof (buf), fp) != NULL) {
|
|
||||||
/* Remove optional trailing '\n'. */
|
|
||||||
buf[strcspn (buf, "\n")] = '\0';
|
|
||||||
if (strcmp (buf, tty) == 0) {
|
|
||||||
(void) fclose (fp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This tty isn't a console.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(void) fclose (fp);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* console - return 1 if the "tty" is a console device, else 0.
|
|
||||||
*
|
|
||||||
* Note - we need to take extreme care here to avoid locking out root logins
|
|
||||||
* if something goes awry. That's why we do things like call everything a
|
|
||||||
* console if the consoles file can't be opened. Because of this, we must
|
|
||||||
* warn the user to protect against the remove of the consoles file since
|
|
||||||
* that would allow an unauthorized root login.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool console (const char *tty)
|
|
||||||
{
|
|
||||||
if (strncmp (tty, "/dev/", 5) == 0) {
|
|
||||||
tty += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_listed ("CONSOLE", tty, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
-934
@@ -1,934 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2001, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2006, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2010, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
#include <selinux/selinux.h>
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
#if defined(WITH_ACL) || defined(WITH_ATTR)
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <attr/error_context.h>
|
|
||||||
#endif /* WITH_ACL || WITH_ATTR */
|
|
||||||
#ifdef WITH_ACL
|
|
||||||
#include <acl/libacl.h>
|
|
||||||
#endif /* WITH_ACL */
|
|
||||||
#ifdef WITH_ATTR
|
|
||||||
#include <attr/libattr.h>
|
|
||||||
#endif /* WITH_ATTR */
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
static /*@null@*/const char *src_orig;
|
|
||||||
static /*@null@*/const char *dst_orig;
|
|
||||||
|
|
||||||
struct link_name {
|
|
||||||
dev_t ln_dev;
|
|
||||||
ino_t ln_ino;
|
|
||||||
nlink_t ln_count;
|
|
||||||
char *ln_name;
|
|
||||||
/*@dependent@*/struct link_name *ln_next;
|
|
||||||
};
|
|
||||||
static /*@exposed@*/struct link_name *links;
|
|
||||||
|
|
||||||
struct path_info {
|
|
||||||
const char *full_path;
|
|
||||||
int dirfd;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static /*@null@*/char *readlink_malloc (const char *filename);
|
|
||||||
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
|
||||||
unused bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static int copy_hardlink (const struct path_info *dst,
|
|
||||||
unused bool reset_selinux,
|
|
||||||
struct link_name *lp);
|
|
||||||
static int copy_special (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static int copy_file (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static int chownat_if_needed (const struct path_info *dst, const struct stat *statp,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
static int fchown_if_needed (int fdst, const struct stat *statp,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid);
|
|
||||||
|
|
||||||
#if defined(WITH_ACL) || defined(WITH_ATTR)
|
|
||||||
/*
|
|
||||||
* error_acl - format the error messages for the ACL and EQ libraries.
|
|
||||||
*/
|
|
||||||
format_attr(printf, 2, 3)
|
|
||||||
static void error_acl (unused struct error_context *ctx, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
FILE *shadow_logfd = log_get_logfd();
|
|
||||||
|
|
||||||
/* ignore the case when destination does not support ACLs
|
|
||||||
* or extended attributes */
|
|
||||||
if (ENOTSUP == errno) {
|
|
||||||
errno = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start (ap, fmt);
|
|
||||||
(void) fprintf (shadow_logfd, _("%s: "), log_get_progname());
|
|
||||||
if (vfprintf (shadow_logfd, fmt, ap) != 0) {
|
|
||||||
(void) fputs (_(": "), shadow_logfd);
|
|
||||||
}
|
|
||||||
(void) fprintf (shadow_logfd, "%s\n", strerror (errno));
|
|
||||||
va_end (ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct error_context ctx = {
|
|
||||||
error_acl, NULL, NULL
|
|
||||||
};
|
|
||||||
#endif /* WITH_ACL || WITH_ATTR */
|
|
||||||
|
|
||||||
#ifdef WITH_ACL
|
|
||||||
static int perm_copy_path(const struct path_info *src,
|
|
||||||
const struct path_info *dst,
|
|
||||||
struct error_context *errctx)
|
|
||||||
{
|
|
||||||
int src_fd, dst_fd, ret;
|
|
||||||
|
|
||||||
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
|
||||||
if (src_fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
|
||||||
if (dst_fd < 0) {
|
|
||||||
(void) close (src_fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = perm_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, errctx);
|
|
||||||
(void) close (src_fd);
|
|
||||||
(void) close (dst_fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* WITH_ACL */
|
|
||||||
|
|
||||||
#ifdef WITH_ATTR
|
|
||||||
static int attr_copy_path(const struct path_info *src,
|
|
||||||
const struct path_info *dst,
|
|
||||||
int (*callback) (const char *, struct error_context *),
|
|
||||||
struct error_context *errctx)
|
|
||||||
{
|
|
||||||
int src_fd, dst_fd, ret;
|
|
||||||
|
|
||||||
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
|
||||||
if (src_fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
|
||||||
if (dst_fd < 0) {
|
|
||||||
(void) close (src_fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = attr_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, callback, errctx);
|
|
||||||
(void) close (src_fd);
|
|
||||||
(void) close (dst_fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* WITH_ATTR */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* remove_link - delete a link from the linked list
|
|
||||||
*/
|
|
||||||
static void remove_link (/*@only@*/struct link_name *ln)
|
|
||||||
{
|
|
||||||
struct link_name *lp;
|
|
||||||
|
|
||||||
if (links == ln) {
|
|
||||||
links = ln->ln_next;
|
|
||||||
free (ln->ln_name);
|
|
||||||
free (ln);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (lp = links; NULL !=lp; lp = lp->ln_next) {
|
|
||||||
if (lp->ln_next == ln) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == lp) {
|
|
||||||
free (ln->ln_name);
|
|
||||||
free (ln);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lp->ln_next = lp->ln_next->ln_next;
|
|
||||||
free (ln->ln_name);
|
|
||||||
free (ln);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check_link - see if a file is really a link
|
|
||||||
*/
|
|
||||||
|
|
||||||
static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb)
|
|
||||||
{
|
|
||||||
struct link_name *lp;
|
|
||||||
size_t src_len;
|
|
||||||
size_t dst_len;
|
|
||||||
size_t name_len;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* copy_tree () must be the entry point */
|
|
||||||
assert (NULL != src_orig);
|
|
||||||
assert (NULL != dst_orig);
|
|
||||||
|
|
||||||
for (lp = links; NULL != lp; lp = lp->ln_next) {
|
|
||||||
if ((lp->ln_dev == sb->st_dev) && (lp->ln_ino == sb->st_ino)) {
|
|
||||||
return lp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb->st_nlink == 1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lp = XMALLOC(1, struct link_name);
|
|
||||||
src_len = strlen (src_orig);
|
|
||||||
dst_len = strlen (dst_orig);
|
|
||||||
name_len = strlen (name);
|
|
||||||
lp->ln_dev = sb->st_dev;
|
|
||||||
lp->ln_ino = sb->st_ino;
|
|
||||||
lp->ln_count = sb->st_nlink;
|
|
||||||
len = name_len - src_len + dst_len + 1;
|
|
||||||
lp->ln_name = XMALLOC(len, char);
|
|
||||||
(void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
|
|
||||||
lp->ln_next = links;
|
|
||||||
links = lp;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int copy_tree_impl (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool copy_root, bool reset_selinux,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
int dst_fd, src_fd, err = 0;
|
|
||||||
bool set_orig = false;
|
|
||||||
const struct dirent *ent;
|
|
||||||
DIR *dir;
|
|
||||||
|
|
||||||
if (copy_root) {
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if ( fstatat (dst->dirfd, dst->name, &sb, 0) == 0
|
|
||||||
|| errno != ENOENT) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fstatat (src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISDIR (sb.st_mode)) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
"%s: %s is not a directory",
|
|
||||||
log_get_progname(), src->full_path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy_entry (src, dst, reset_selinux,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make certain both directories exist. This routine is called
|
|
||||||
* after the home directory is created, or recursively after the
|
|
||||||
* target is created. It assumes the target directory exists.
|
|
||||||
*/
|
|
||||||
|
|
||||||
src_fd = openat (src->dirfd, src->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
|
||||||
if (src_fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_fd = openat (dst->dirfd, dst->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
|
||||||
if (dst_fd < 0) {
|
|
||||||
(void) close (src_fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the source directory and read each entry. Every file
|
|
||||||
* entry in the directory is copied with the UID and GID set
|
|
||||||
* to the provided values. As an added security feature only
|
|
||||||
* regular files (and directories ...) are copied, and no file
|
|
||||||
* is made set-ID.
|
|
||||||
*/
|
|
||||||
dir = fdopendir (src_fd);
|
|
||||||
if (NULL == dir) {
|
|
||||||
(void) close (src_fd);
|
|
||||||
(void) close (dst_fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src_orig == NULL) {
|
|
||||||
src_orig = src->full_path;
|
|
||||||
dst_orig = dst->full_path;
|
|
||||||
set_orig = true;
|
|
||||||
}
|
|
||||||
while ((0 == err) && (ent = readdir (dir)) != NULL) {
|
|
||||||
/*
|
|
||||||
* Skip the "." and ".." entries
|
|
||||||
*/
|
|
||||||
if ((strcmp (ent->d_name, ".") != 0) &&
|
|
||||||
(strcmp (ent->d_name, "..") != 0)) {
|
|
||||||
char *src_name;
|
|
||||||
char *dst_name;
|
|
||||||
size_t src_len = strlen (ent->d_name) + 2;
|
|
||||||
size_t dst_len = strlen (ent->d_name) + 2;
|
|
||||||
src_len += strlen (src->full_path);
|
|
||||||
dst_len += strlen (dst->full_path);
|
|
||||||
|
|
||||||
src_name = MALLOC(src_len, char);
|
|
||||||
dst_name = MALLOC(dst_len, char);
|
|
||||||
|
|
||||||
if ((NULL == src_name) || (NULL == dst_name)) {
|
|
||||||
err = -1;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Build the filename for both the source and
|
|
||||||
* the destination files.
|
|
||||||
*/
|
|
||||||
struct path_info src_entry, dst_entry;
|
|
||||||
|
|
||||||
(void) snprintf (src_name, src_len, "%s/%s",
|
|
||||||
src->full_path, ent->d_name);
|
|
||||||
(void) snprintf (dst_name, dst_len, "%s/%s",
|
|
||||||
dst->full_path, ent->d_name);
|
|
||||||
|
|
||||||
src_entry.full_path = src_name;
|
|
||||||
src_entry.dirfd = dirfd(dir);
|
|
||||||
src_entry.name = ent->d_name;
|
|
||||||
|
|
||||||
dst_entry.full_path = dst_name;
|
|
||||||
dst_entry.dirfd = dst_fd;
|
|
||||||
dst_entry.name = ent->d_name;
|
|
||||||
|
|
||||||
err = copy_entry (&src_entry, &dst_entry,
|
|
||||||
reset_selinux,
|
|
||||||
old_uid, new_uid,
|
|
||||||
old_gid, new_gid);
|
|
||||||
}
|
|
||||||
free (src_name);
|
|
||||||
free (dst_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) closedir (dir);
|
|
||||||
(void) close (dst_fd);
|
|
||||||
|
|
||||||
if (set_orig) {
|
|
||||||
src_orig = NULL;
|
|
||||||
dst_orig = NULL;
|
|
||||||
/* FIXME: clean links
|
|
||||||
* Since there can be hardlinks elsewhere on the device,
|
|
||||||
* we cannot check that all the hardlinks were found:
|
|
||||||
assert (NULL == links);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
/* Reset SELinux to create files with default contexts.
|
|
||||||
* Note that the context is only reset on exit of copy_tree (it is
|
|
||||||
* assumed that the program would quit without needing a restored
|
|
||||||
* context if copy_tree failed previously), and that copy_tree can
|
|
||||||
* be called recursively (hence the context is set on the
|
|
||||||
* sub-functions of copy_entry).
|
|
||||||
*/
|
|
||||||
if (reset_selinux_file_context () != 0) {
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_entry - copy the entry of a directory
|
|
||||||
*
|
|
||||||
* Copy the entry src to dst.
|
|
||||||
* Depending on the type of entry, this function will forward the
|
|
||||||
* request to copy_dir(), copy_symlink(), copy_hardlink(),
|
|
||||||
* copy_special(), or copy_file().
|
|
||||||
*
|
|
||||||
* The access and modification time will not be modified.
|
|
||||||
*
|
|
||||||
* The permissions will be set to new_uid/new_gid.
|
|
||||||
*
|
|
||||||
* If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will
|
|
||||||
* not be modified.
|
|
||||||
*
|
|
||||||
* Only the files owned (resp. group-owned) by old_uid (resp.
|
|
||||||
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
|
|
||||||
* to -1.
|
|
||||||
*/
|
|
||||||
static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
struct stat sb;
|
|
||||||
struct link_name *lp;
|
|
||||||
struct timespec mt[2];
|
|
||||||
|
|
||||||
if (fstatat(src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
|
|
||||||
/* If we cannot stat the file, do not care. */
|
|
||||||
} else {
|
|
||||||
mt[0].tv_sec = sb.st_atim.tv_sec;
|
|
||||||
mt[0].tv_nsec = sb.st_atim.tv_nsec;
|
|
||||||
|
|
||||||
mt[1].tv_sec = sb.st_mtim.tv_sec;
|
|
||||||
mt[1].tv_nsec = sb.st_mtim.tv_nsec;
|
|
||||||
|
|
||||||
if (S_ISDIR (sb.st_mode)) {
|
|
||||||
err = copy_dir (src, dst, reset_selinux, &sb, mt,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the destination already exists do nothing.
|
|
||||||
* This is after the copy_dir above to still iterate into subdirectories.
|
|
||||||
*/
|
|
||||||
if (fstatat(dst->dirfd, dst->name, &sb, AT_SYMLINK_NOFOLLOW) != -1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy any symbolic links
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (S_ISLNK (sb.st_mode)) {
|
|
||||||
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if this is a previously copied link
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if ((lp = check_link (src->full_path, &sb)) != NULL) {
|
|
||||||
err = copy_hardlink (dst, reset_selinux, lp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deal with FIFOs and special files. The user really
|
|
||||||
* shouldn't have any of these, but it seems like it
|
|
||||||
* would be nice to copy everything ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (!S_ISREG (sb.st_mode)) {
|
|
||||||
err = copy_special (src, dst, reset_selinux, &sb, mt,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create the new file and copy the contents. The new
|
|
||||||
* file will be owned by the provided UID and GID values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else {
|
|
||||||
err = copy_file (src, dst, reset_selinux, &sb, mt,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_dir - copy a directory
|
|
||||||
*
|
|
||||||
* Copy a directory (recursively) from src to dst.
|
|
||||||
*
|
|
||||||
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
|
|
||||||
* the access and modification and the access rights.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
struct stat dst_sb;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new target directory, make it owned by
|
|
||||||
* the user and then recursively copy that directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
if (set_selinux_file_context (dst->full_path, S_IFDIR) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
/*
|
|
||||||
* If the destination is already a directory, don't change it
|
|
||||||
* but copy into it (recursively).
|
|
||||||
*/
|
|
||||||
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
|
|
||||||
return (copy_tree_impl (src, dst, false, reset_selinux,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (mkdirat (dst->dirfd, dst->name, 0700) != 0)
|
|
||||||
|| (chownat_if_needed (dst, statp,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0)
|
|
||||||
|| (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
|
|
||||||
#ifdef WITH_ACL
|
|
||||||
|| ( (perm_copy_path (src, dst, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ACL */
|
|
||||||
#ifdef WITH_ATTR
|
|
||||||
/*
|
|
||||||
* If the third parameter is NULL, all extended attributes
|
|
||||||
* except those that define Access Control Lists are copied.
|
|
||||||
* ACLs are excluded by default because copying them between
|
|
||||||
* file systems with and without ACL support needs some
|
|
||||||
* additional logic so that no unexpected permissions result.
|
|
||||||
*/
|
|
||||||
|| ( !reset_selinux
|
|
||||||
&& (attr_copy_path (src, dst, NULL, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ATTR */
|
|
||||||
|| (copy_tree_impl (src, dst, false, reset_selinux,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0)
|
|
||||||
|| (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readlink_malloc - wrapper for readlink
|
|
||||||
*
|
|
||||||
* return NULL on error.
|
|
||||||
* The return string shall be freed by the caller.
|
|
||||||
*/
|
|
||||||
static /*@null@*/char *readlink_malloc (const char *filename)
|
|
||||||
{
|
|
||||||
size_t size = 1024;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
ssize_t nchars;
|
|
||||||
char *buffer = MALLOC(size, char);
|
|
||||||
if (NULL == buffer) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nchars = readlink (filename, buffer, size);
|
|
||||||
|
|
||||||
if (nchars < 0) {
|
|
||||||
free(buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_t) nchars < size) { /* The buffer was large enough */
|
|
||||||
/* readlink does not nul-terminate */
|
|
||||||
buffer[nchars] = '\0';
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try again with a bigger buffer */
|
|
||||||
free (buffer);
|
|
||||||
size *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_symlink - copy a symlink
|
|
||||||
*
|
|
||||||
* Copy a symlink from src to dst.
|
|
||||||
*
|
|
||||||
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
|
|
||||||
* the access and modification and the access rights.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
|
||||||
unused bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
char *oldlink;
|
|
||||||
|
|
||||||
/* copy_tree () must be the entry point */
|
|
||||||
assert (NULL != src_orig);
|
|
||||||
assert (NULL != dst_orig);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the name of the file which the link points
|
|
||||||
* to. If that name begins with the original
|
|
||||||
* source directory name, that part of the link
|
|
||||||
* name will be replaced with the original
|
|
||||||
* destination directory name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
oldlink = readlink_malloc (src->full_path);
|
|
||||||
if (NULL == oldlink) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If src was a link to an entry of the src_orig directory itself,
|
|
||||||
* create a link to the corresponding entry in the dst_orig
|
|
||||||
* directory.
|
|
||||||
*/
|
|
||||||
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
|
|
||||||
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
|
|
||||||
char *dummy = XMALLOC(len, char);
|
|
||||||
(void) snprintf (dummy, len, "%s%s",
|
|
||||||
dst_orig,
|
|
||||||
oldlink + strlen (src_orig));
|
|
||||||
free (oldlink);
|
|
||||||
oldlink = dummy;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
if (set_selinux_file_context (dst->full_path, S_IFLNK) != 0) {
|
|
||||||
free (oldlink);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
if ( (symlinkat (oldlink, dst->dirfd, dst->name) != 0)
|
|
||||||
|| (chownat_if_needed (dst, statp,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0)) {
|
|
||||||
/* FIXME: there are no modes on symlinks, right?
|
|
||||||
* ACL could be copied, but this would be much more
|
|
||||||
* complex than calling perm_copy_file.
|
|
||||||
* Ditto for Extended Attributes.
|
|
||||||
* We currently only document that ACL and Extended
|
|
||||||
* Attributes are not copied.
|
|
||||||
*/
|
|
||||||
free (oldlink);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free (oldlink);
|
|
||||||
|
|
||||||
if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_hardlink - copy a hardlink
|
|
||||||
*
|
|
||||||
* Copy a hardlink from src to dst.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int copy_hardlink (const struct path_info *dst,
|
|
||||||
unused bool reset_selinux,
|
|
||||||
struct link_name *lp)
|
|
||||||
{
|
|
||||||
/* FIXME: selinux, ACL, Extended Attributes needed? */
|
|
||||||
|
|
||||||
if (linkat (AT_FDCWD, lp->ln_name, dst->dirfd, dst->name, 0) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the file could be unlinked, decrement the links counter,
|
|
||||||
* and forget about this link if it was the last reference */
|
|
||||||
lp->ln_count--;
|
|
||||||
if (lp->ln_count <= 0) {
|
|
||||||
remove_link (lp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_special - copy a special file
|
|
||||||
*
|
|
||||||
* Copy a special file from src to dst.
|
|
||||||
*
|
|
||||||
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
|
|
||||||
* the access and modification and the access rights.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int copy_special (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
if (set_selinux_file_context (dst->full_path, statp->st_mode & S_IFMT) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
|
|
||||||
if ( (mknodat (dst->dirfd, dst->name, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|
|
||||||
|| (chownat_if_needed (dst, statp,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0)
|
|
||||||
|| (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
|
|
||||||
#ifdef WITH_ACL
|
|
||||||
|| ( (perm_copy_path (src, dst, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ACL */
|
|
||||||
#ifdef WITH_ATTR
|
|
||||||
/*
|
|
||||||
* If the third parameter is NULL, all extended attributes
|
|
||||||
* except those that define Access Control Lists are copied.
|
|
||||||
* ACLs are excluded by default because copying them between
|
|
||||||
* file systems with and without ACL support needs some
|
|
||||||
* additional logic so that no unexpected permissions result.
|
|
||||||
*/
|
|
||||||
|| ( !reset_selinux
|
|
||||||
&& (attr_copy_path (src, dst, NULL, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ATTR */
|
|
||||||
|| (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_file - copy a file
|
|
||||||
*
|
|
||||||
* Copy a file from src to dst.
|
|
||||||
*
|
|
||||||
* statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
|
|
||||||
* the access and modification and the access rights.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int copy_file (const struct path_info *src, const struct path_info *dst,
|
|
||||||
bool reset_selinux,
|
|
||||||
const struct stat *statp, const struct timespec mt[],
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
int ifd;
|
|
||||||
int ofd;
|
|
||||||
|
|
||||||
ifd = openat (src->dirfd, src->name, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
|
|
||||||
if (ifd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
if (set_selinux_file_context (dst->full_path, S_IFREG) != 0) {
|
|
||||||
(void) close (ifd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SELINUX */
|
|
||||||
ofd = openat (dst->dirfd, dst->name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0600);
|
|
||||||
if ( (ofd < 0)
|
|
||||||
|| (fchown_if_needed (ofd, statp,
|
|
||||||
old_uid, new_uid, old_gid, new_gid) != 0)
|
|
||||||
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
|
|
||||||
#ifdef WITH_ACL
|
|
||||||
|| ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ACL */
|
|
||||||
#ifdef WITH_ATTR
|
|
||||||
/*
|
|
||||||
* If the third parameter is NULL, all extended attributes
|
|
||||||
* except those that define Access Control Lists are copied.
|
|
||||||
* ACLs are excluded by default because copying them between
|
|
||||||
* file systems with and without ACL support needs some
|
|
||||||
* additional logic so that no unexpected permissions result.
|
|
||||||
*/
|
|
||||||
|| ( !reset_selinux
|
|
||||||
&& (attr_copy_fd (src->full_path, ifd, dst->full_path, ofd, NULL, &ctx) != 0)
|
|
||||||
&& (errno != 0))
|
|
||||||
#endif /* WITH_ATTR */
|
|
||||||
) {
|
|
||||||
if (ofd >= 0) {
|
|
||||||
(void) close (ofd);
|
|
||||||
}
|
|
||||||
(void) close (ifd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char buf[8192];
|
|
||||||
ssize_t cnt;
|
|
||||||
|
|
||||||
cnt = read (ifd, buf, sizeof buf);
|
|
||||||
if (cnt < 0) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
(void) close (ofd);
|
|
||||||
(void) close (ifd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (cnt == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write_full (ofd, buf, cnt) < 0) {
|
|
||||||
(void) close (ofd);
|
|
||||||
(void) close (ifd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) close (ifd);
|
|
||||||
if (close (ofd) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define def_chown_if_needed(chown_function, type_dst) \
|
|
||||||
static int chown_function ## _if_needed (type_dst dst, \
|
|
||||||
const struct stat *statp, \
|
|
||||||
uid_t old_uid, uid_t new_uid, \
|
|
||||||
gid_t old_gid, gid_t new_gid) \
|
|
||||||
{ \
|
|
||||||
uid_t tmpuid = (uid_t) -1; \
|
|
||||||
gid_t tmpgid = (gid_t) -1; \
|
|
||||||
\
|
|
||||||
/* Use new_uid if old_uid is set to -1 or if the file was \
|
|
||||||
* owned by the user. */ \
|
|
||||||
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
|
|
||||||
tmpuid = new_uid; \
|
|
||||||
} \
|
|
||||||
/* Otherwise, or if new_uid was set to -1, we keep the same \
|
|
||||||
* owner. */ \
|
|
||||||
if ((uid_t) -1 == tmpuid) { \
|
|
||||||
tmpuid = statp->st_uid; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
|
|
||||||
tmpgid = new_gid; \
|
|
||||||
} \
|
|
||||||
if ((gid_t) -1 == tmpgid) { \
|
|
||||||
tmpgid = statp->st_gid; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return chown_function (dst, tmpuid, tmpgid); \
|
|
||||||
}
|
|
||||||
|
|
||||||
def_chown_if_needed (fchown, int)
|
|
||||||
|
|
||||||
static int chownat_if_needed (const struct path_info *dst,
|
|
||||||
const struct stat *statp,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
uid_t tmpuid = (uid_t) -1;
|
|
||||||
gid_t tmpgid = (gid_t) -1;
|
|
||||||
|
|
||||||
/* Use new_uid if old_uid is set to -1 or if the file was
|
|
||||||
* owned by the user. */
|
|
||||||
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) {
|
|
||||||
tmpuid = new_uid;
|
|
||||||
}
|
|
||||||
/* Otherwise, or if new_uid was set to -1, we keep the same
|
|
||||||
* owner. */
|
|
||||||
if ((uid_t) -1 == tmpuid) {
|
|
||||||
tmpuid = statp->st_uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) {
|
|
||||||
tmpgid = new_gid;
|
|
||||||
}
|
|
||||||
if ((gid_t) -1 == tmpgid) {
|
|
||||||
tmpgid = statp->st_gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fchownat (dst->dirfd, dst->name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_tree - copy files in a directory tree
|
|
||||||
*
|
|
||||||
* copy_tree() walks a directory tree and copies ordinary files
|
|
||||||
* as it goes.
|
|
||||||
*
|
|
||||||
* When reset_selinux is enabled, extended attributes (and thus
|
|
||||||
* SELinux attributes) are not copied.
|
|
||||||
*
|
|
||||||
* old_uid and new_uid are used to set the ownership of the copied
|
|
||||||
* files. Unless old_uid is set to -1, only the files owned by
|
|
||||||
* old_uid have their ownership changed to new_uid. In addition, if
|
|
||||||
* new_uid is set to -1, no ownership will be changed.
|
|
||||||
*
|
|
||||||
* The same logic applies for the group-ownership and
|
|
||||||
* old_gid/new_gid.
|
|
||||||
*/
|
|
||||||
int copy_tree (const char *src_root, const char *dst_root,
|
|
||||||
bool copy_root, bool reset_selinux,
|
|
||||||
uid_t old_uid, uid_t new_uid,
|
|
||||||
gid_t old_gid, gid_t new_gid)
|
|
||||||
{
|
|
||||||
const struct path_info src = {
|
|
||||||
.full_path = src_root,
|
|
||||||
.dirfd = AT_FDCWD,
|
|
||||||
.name = src_root
|
|
||||||
};
|
|
||||||
const struct path_info dst = {
|
|
||||||
.full_path = dst_root,
|
|
||||||
.dirfd = AT_FDCWD,
|
|
||||||
.name = dst_root
|
|
||||||
};
|
|
||||||
|
|
||||||
return copy_tree_impl(&src, &dst, copy_root, reset_selinux,
|
|
||||||
old_uid, new_uid, old_gid, new_gid);
|
|
||||||
}
|
|
||||||
-141
@@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: Alejandro Colomar <alx@kernel.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#if HAVE_SYS_RANDOM_H
|
|
||||||
#include <sys/random.h>
|
|
||||||
#endif
|
|
||||||
#include "bit.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t csrand_uniform32(uint32_t n);
|
|
||||||
static unsigned long csrand_uniform_slow(unsigned long n);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a uniformly-distributed CS random u_long value.
|
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
csrand(void)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
unsigned long r;
|
|
||||||
|
|
||||||
#ifdef HAVE_GETENTROPY
|
|
||||||
/* getentropy may exist but lack kernel support. */
|
|
||||||
if (getentropy(&r, sizeof(r)) == 0)
|
|
||||||
return r;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM
|
|
||||||
/* Likewise getrandom. */
|
|
||||||
if (getrandom(&r, sizeof(r), 0) == sizeof(r))
|
|
||||||
return r;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_ARC4RANDOM_BUF
|
|
||||||
/* arc4random_buf can never fail. */
|
|
||||||
arc4random_buf(&r, sizeof(r));
|
|
||||||
return r;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Use /dev/urandom as a last resort. */
|
|
||||||
fp = fopen("/dev/urandom", "r");
|
|
||||||
if (NULL == fp) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fread(&r, sizeof(r), 1, fp) != 1) {
|
|
||||||
fclose(fp);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
return r;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
fprintf(log_get_logfd(), _("Unable to obtain random bytes.\n"));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a uniformly-distributed CS random value in the interval [0, n-1].
|
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
csrand_uniform(unsigned long n)
|
|
||||||
{
|
|
||||||
if (n == 0 || n > UINT32_MAX)
|
|
||||||
return csrand_uniform_slow(n);
|
|
||||||
|
|
||||||
return csrand_uniform32(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a uniformly-distributed CS random value in the interval [min, max].
|
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
csrand_interval(unsigned long min, unsigned long max)
|
|
||||||
{
|
|
||||||
return csrand_uniform(max - min + 1) + min;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fast Random Integer Generation in an Interval
|
|
||||||
* ACM Transactions on Modeling and Computer Simulation 29 (1), 2019
|
|
||||||
* <https://arxiv.org/abs/1805.10941>
|
|
||||||
*/
|
|
||||||
static uint32_t
|
|
||||||
csrand_uniform32(uint32_t n)
|
|
||||||
{
|
|
||||||
uint32_t bound, rem;
|
|
||||||
uint64_t r, mult;
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return csrand();
|
|
||||||
|
|
||||||
bound = -n % n; // analogous to `2^32 % n`, since `x % y == (x-y) % y`
|
|
||||||
|
|
||||||
do {
|
|
||||||
r = csrand();
|
|
||||||
mult = r * n;
|
|
||||||
rem = mult; // analogous to `mult % 2^32`
|
|
||||||
} while (rem < bound); // p = (2^32 % n) / 2^32; W.C.: n=2^31+1, p=0.5
|
|
||||||
|
|
||||||
r = mult >> WIDTHOF(n); // analogous to `mult / 2^32`
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned long
|
|
||||||
csrand_uniform_slow(unsigned long n)
|
|
||||||
{
|
|
||||||
unsigned long r, max, mask;
|
|
||||||
|
|
||||||
max = n - 1;
|
|
||||||
mask = bit_ceil_wrapul(n) - 1;
|
|
||||||
|
|
||||||
do {
|
|
||||||
r = csrand();
|
|
||||||
r &= mask; // optimization
|
|
||||||
} while (r > max); // p = ((mask+1) % n) / (mask+1); W.C.: p=0.5
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2021, Alejandro Colomar <alx.manpages@gmail.com>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the copyright holders or contributors may not be used to
|
|
||||||
* endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
date_to_str(size_t size, char buf[size], long date)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
const struct tm *tm;
|
|
||||||
|
|
||||||
t = date;
|
|
||||||
if (date < 0) {
|
|
||||||
(void) strlcpy(buf, "never", size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm = gmtime(&t);
|
|
||||||
if (tm == NULL) {
|
|
||||||
(void) strlcpy(buf, "future", size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) strftime(buf, size, "%Y-%m-%d", tm);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
+150
-76
@@ -4,64 +4,98 @@
|
|||||||
#ifndef _DEFINES_H_
|
#ifndef _DEFINES_H_
|
||||||
#define _DEFINES_H_
|
#define _DEFINES_H_
|
||||||
|
|
||||||
#include "config.h"
|
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
|
||||||
|
|
||||||
#include <stdbool.h>
|
/* Take care of NLS matters. */
|
||||||
#include <locale.h>
|
|
||||||
|
#if HAVE_LOCALE_H
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define gettext_noop(String) (String)
|
#define gettext_noop(String) (String)
|
||||||
/* #define gettext_def(String) "#define String" */
|
/* #define gettext_def(String) "#define String" */
|
||||||
|
|
||||||
#ifdef ENABLE_NLS
|
#if ENABLE_NLS
|
||||||
# include <libintl.h>
|
# include <libintl.h>
|
||||||
# define _(Text) gettext (Text)
|
# define _(Text) gettext (Text)
|
||||||
#else
|
#else
|
||||||
# undef bindtextdomain
|
# undef bindtextdomain
|
||||||
# define bindtextdomain(Domain, Directory) (NULL)
|
# define bindtextdomain(Domain, Directory) /* empty */
|
||||||
# undef textdomain
|
# undef textdomain
|
||||||
# define textdomain(Domain) (NULL)
|
# define textdomain(Domain) /* empty */
|
||||||
# define _(Text) Text
|
# define _(Text) Text
|
||||||
# define ngettext(Msgid1, Msgid2, N) \
|
# define ngettext(Msgid1, Msgid2, N) \
|
||||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#if STDC_HEADERS
|
||||||
#include <string.h>
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
#else /* not STDC_HEADERS */
|
||||||
|
# ifndef HAVE_STRCHR
|
||||||
|
# define strchr index
|
||||||
|
# define strrchr rindex
|
||||||
|
# endif
|
||||||
|
char *strchr (), *strrchr (), *strtok ();
|
||||||
|
|
||||||
#include <errno.h>
|
# ifndef HAVE_MEMCPY
|
||||||
|
# define memcpy(d, s, n) bcopy((s), (d), (n))
|
||||||
|
# endif
|
||||||
|
#endif /* not STDC_HEADERS */
|
||||||
|
|
||||||
|
#if HAVE_ERRNO_H
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#if HAVE_SYS_WAIT_H
|
||||||
|
# include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#endif
|
||||||
|
#ifndef WEXITSTATUS
|
||||||
/*
|
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
|
||||||
* crypt(3), crypt_gensalt(3), and their
|
#endif
|
||||||
* feature test macros may be defined in here.
|
#ifndef WIFEXITED
|
||||||
*/
|
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
|
||||||
#if HAVE_CRYPT_H
|
|
||||||
# include <crypt.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/time.h>
|
#if HAVE_UNISTD_H
|
||||||
#include <time.h>
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_MEMSET_EXPLICIT
|
#if TIME_WITH_SYS_TIME
|
||||||
# define memzero(ptr, size) memset_explicit((ptr), 0, (size))
|
# include <sys/time.h>
|
||||||
#elif defined HAVE_EXPLICIT_BZERO /* !HAVE_MEMSET_S */
|
# include <time.h>
|
||||||
# define memzero(ptr, size) explicit_bzero((ptr), (size))
|
#else /* not TIME_WITH_SYS_TIME */
|
||||||
#else /* !HAVE_MEMSET_S && HAVE_EXPLICIT_BZERO */
|
# if HAVE_SYS_TIME_H
|
||||||
static inline void memzero(void *ptr, size_t size)
|
# include <sys/time.h>
|
||||||
{
|
# else
|
||||||
ptr = memset(ptr, '\0', size);
|
# include <time.h>
|
||||||
__asm__ __volatile__ ("" : : "r"(ptr) : "memory");
|
# endif
|
||||||
}
|
#endif /* not TIME_WITH_SYS_TIME */
|
||||||
#endif /* !HAVE_MEMSET_S && !HAVE_EXPLICIT_BZERO */
|
|
||||||
|
|
||||||
|
#ifdef HAVE_MEMSET
|
||||||
|
# define memzero(ptr, size) memset((void *)(ptr), 0, (size))
|
||||||
|
#else
|
||||||
|
# define memzero(ptr, size) bzero((char *)(ptr), (size))
|
||||||
|
#endif
|
||||||
#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */
|
#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */
|
||||||
|
|
||||||
#include <dirent.h>
|
#ifdef HAVE_DIRENT_H /* DIR_SYSV */
|
||||||
|
# include <dirent.h>
|
||||||
|
# define DIRECT dirent
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_SYS_NDIR_H /* DIR_XENIX */
|
||||||
|
# include <sys/ndir.h>
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_SYS_DIR_H /* DIR_??? */
|
||||||
|
# include <sys/dir.h>
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_NDIR_H /* DIR_BSD */
|
||||||
|
# include <ndir.h>
|
||||||
|
# endif
|
||||||
|
# define DIRECT direct
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Possible cases:
|
* Possible cases:
|
||||||
@@ -83,6 +117,7 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#ifndef LOG_WARN
|
#ifndef LOG_WARN
|
||||||
@@ -101,7 +136,7 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
|
|
||||||
/* cleaner than lots of #ifdefs everywhere - use this as follows:
|
/* cleaner than lots of #ifdefs everywhere - use this as follows:
|
||||||
SYSLOG((LOG_CRIT, "user %s cracked root", user)); */
|
SYSLOG((LOG_CRIT, "user %s cracked root", user)); */
|
||||||
#ifdef ENABLE_NLS
|
#if ENABLE_NLS
|
||||||
/* Temporarily set LC_TIME to "C" to avoid strange dates in syslog.
|
/* Temporarily set LC_TIME to "C" to avoid strange dates in syslog.
|
||||||
This is a workaround for a more general syslog(d) design problem -
|
This is a workaround for a more general syslog(d) design problem -
|
||||||
syslogd should log the current system time for each event, and not
|
syslogd should log the current system time for each event, and not
|
||||||
@@ -111,24 +146,29 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
* --Nekral */
|
* --Nekral */
|
||||||
#define SYSLOG(x) \
|
#define SYSLOG(x) \
|
||||||
do { \
|
do { \
|
||||||
char *old_locale = setlocale (LC_ALL, NULL); \
|
char *saved_locale = setlocale(LC_ALL, NULL); \
|
||||||
char *saved_locale = NULL; \
|
if (saved_locale) \
|
||||||
if (NULL != old_locale) { \
|
saved_locale = strdup(saved_locale); \
|
||||||
saved_locale = strdup (old_locale); \
|
if (saved_locale) \
|
||||||
} \
|
setlocale(LC_ALL, "C"); \
|
||||||
if (NULL != saved_locale) { \
|
|
||||||
(void) setlocale (LC_ALL, "C"); \
|
|
||||||
} \
|
|
||||||
syslog x ; \
|
syslog x ; \
|
||||||
if (NULL != saved_locale) { \
|
if (saved_locale) { \
|
||||||
(void) setlocale (LC_ALL, saved_locale); \
|
setlocale(LC_ALL, saved_locale); \
|
||||||
free (saved_locale); \
|
free(saved_locale); \
|
||||||
} \
|
} \
|
||||||
} while (false)
|
} while (0)
|
||||||
#else /* !ENABLE_NLS */
|
#else /* !ENABLE_NLS */
|
||||||
#define SYSLOG(x) syslog x
|
#define SYSLOG(x) syslog x
|
||||||
#endif /* !ENABLE_NLS */
|
#endif /* !ENABLE_NLS */
|
||||||
|
|
||||||
|
#else /* !USE_SYSLOG */
|
||||||
|
|
||||||
|
#define SYSLOG(x) /* empty */
|
||||||
|
#define openlog(a,b,c) /* empty */
|
||||||
|
#define closelog() /* empty */
|
||||||
|
|
||||||
|
#endif /* !USE_SYSLOG */
|
||||||
|
|
||||||
/* The default syslog settings can now be changed here,
|
/* The default syslog settings can now be changed here,
|
||||||
in just one place. */
|
in just one place. */
|
||||||
|
|
||||||
@@ -143,10 +183,57 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
|
|
||||||
#define OPENLOG(progname) openlog(progname, SYSLOG_OPTIONS, SYSLOG_FACILITY)
|
#define OPENLOG(progname) openlog(progname, SYSLOG_OPTIONS, SYSLOG_FACILITY)
|
||||||
|
|
||||||
#include <termios.h>
|
#ifndef F_OK
|
||||||
#define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
|
# define F_OK 0
|
||||||
#define GTTY(fd, termio) tcgetattr(fd, termio)
|
# define X_OK 1
|
||||||
#define TERMIO struct termios
|
# define W_OK 2
|
||||||
|
# define R_OK 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
# define SEEK_SET 0
|
||||||
|
# define SEEK_CUR 1
|
||||||
|
# define SEEK_END 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STAT_MACROS_BROKEN
|
||||||
|
# define S_ISDIR(x) ((x) & S_IFMT) == S_IFDIR)
|
||||||
|
# define S_ISREG(x) ((x) & S_IFMT) == S_IFREG)
|
||||||
|
# ifdef S_IFLNK
|
||||||
|
# define S_ISLNK(x) ((x) & S_IFMT) == S_IFLNK)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef S_ISLNK
|
||||||
|
#define S_ISLNK(x) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LCHOWN
|
||||||
|
#define LCHOWN lchown
|
||||||
|
#else
|
||||||
|
#define LCHOWN chown
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LSTAT
|
||||||
|
#define LSTAT lstat
|
||||||
|
#else
|
||||||
|
#define LSTAT stat
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_TERMIOS_H
|
||||||
|
# include <termios.h>
|
||||||
|
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
|
||||||
|
# define GTTY(fd, termio) tcgetattr(fd, termio)
|
||||||
|
# define TERMIO struct termios
|
||||||
|
# define USE_TERMIOS
|
||||||
|
#else /* assumed HAVE_TERMIO_H */
|
||||||
|
# include <sys/ioctl.h>
|
||||||
|
# include <termio.h>
|
||||||
|
# define STTY(fd, termio) ioctl(fd, TCSETA, termio)
|
||||||
|
# define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
|
||||||
|
# define TEMRIO struct termio
|
||||||
|
# define USE_TERMIO
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Password aging constants
|
* Password aging constants
|
||||||
@@ -169,10 +256,6 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
#define SCALE DAY
|
#define SCALE DAY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WIDTHOF(x) (sizeof(x) * CHAR_BIT)
|
|
||||||
#define NITEMS(arr) (sizeof((arr)) / sizeof((arr)[0]))
|
|
||||||
#define STRLEN(s) (NITEMS(s) - 1)
|
|
||||||
|
|
||||||
/* Copy string pointed by B to array A with size checking. It was originally
|
/* Copy string pointed by B to array A with size checking. It was originally
|
||||||
in lmain.c but is _very_ useful elsewhere. Some setuid root programs with
|
in lmain.c but is _very_ useful elsewhere. Some setuid root programs with
|
||||||
very sloppy coding used to assume that BUFSIZ will always be enough... */
|
very sloppy coding used to assume that BUFSIZ will always be enough... */
|
||||||
@@ -199,6 +282,18 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef sun /* hacks for compiling on SunOS */
|
||||||
|
# ifndef SOLARIS
|
||||||
|
extern int fputs ();
|
||||||
|
extern char *strdup ();
|
||||||
|
extern char *strerror ();
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* string to use for the pw_passwd field in /etc/passwd when using
|
* string to use for the pw_passwd field in /etc/passwd when using
|
||||||
* shadow passwords - most systems use "x" but there are a few
|
* shadow passwords - most systems use "x" but there are a few
|
||||||
@@ -208,8 +303,6 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
#define SHADOW_PASSWD_STRING "x"
|
#define SHADOW_PASSWD_STRING "x"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SHADOW_SP_FLAG_UNSET ((unsigned long int)-1)
|
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
#ifdef __u8 /* in case we use pam < 0.80 */
|
#ifdef __u8 /* in case we use pam < 0.80 */
|
||||||
#undef __u8
|
#undef __u8
|
||||||
@@ -223,28 +316,9 @@ static inline void memzero(void *ptr, size_t size)
|
|||||||
|
|
||||||
/* To be used for verified unused parameters */
|
/* To be used for verified unused parameters */
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
# define unused __attribute__((unused))
|
# define unused __attribute__((unused))
|
||||||
# define NORETURN __attribute__((__noreturn__))
|
|
||||||
# define format_attr(type, index, check) __attribute__((format (type, index, check)))
|
|
||||||
#else
|
#else
|
||||||
# define unused
|
# define unused
|
||||||
# define NORETURN
|
|
||||||
# define format_attr(type, index, check)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Maximum length of passwd entry */
|
|
||||||
#define PASSWD_ENTRY_MAX_LENGTH 32768
|
|
||||||
|
|
||||||
#if (__GNUC__ >= 11) && !defined(__clang__)
|
|
||||||
# define ATTR_MALLOC(deallocator) [[gnu::malloc(deallocator)]]
|
|
||||||
#else
|
|
||||||
# define ATTR_MALLOC(deallocator)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SECURE_GETENV
|
|
||||||
# define shadow_getenv(name) secure_getenv(name)
|
|
||||||
# else
|
|
||||||
# define shadow_getenv(name) getenv(name)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _DEFINES_H_ */
|
#endif /* _DEFINES_H_ */
|
||||||
|
|||||||
+42
-28
@@ -1,10 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1990 - 1993, Julianne Frances Haugh
|
* Copyright (c) 1990 - 1993, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
* Copyright (c) 2005 , Tomasz Kłoczko
|
||||||
* SPDX-FileCopyrightText: 2007 - 2010, Nicolas François
|
* Copyright (c) 2007 - 2008, Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@@ -16,45 +39,39 @@
|
|||||||
|
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "shadowlog_internal.h"
|
|
||||||
|
|
||||||
/*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt)
|
char *pw_encrypt (const char *clear, const char *salt)
|
||||||
{
|
{
|
||||||
static char cipher[128];
|
static char cipher[128];
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
cp = crypt (clear, salt);
|
cp = crypt (clear, salt);
|
||||||
if (NULL == cp) {
|
if (!cp) {
|
||||||
/*
|
/*
|
||||||
* Single Unix Spec: crypt() may return a null pointer,
|
* Single Unix Spec: crypt() may return a null pointer,
|
||||||
* and set errno to indicate an error. In this case return
|
* and set errno to indicate an error. The caller doesn't
|
||||||
* the NULL so the caller can handle appropriately.
|
* expect us to return NULL, so...
|
||||||
*/
|
*/
|
||||||
return NULL;
|
perror ("crypt");
|
||||||
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some crypt() do not return NULL if the algorithm is not
|
/* The GNU crypt does not return NULL if the algorithm is not
|
||||||
* supported, and return a DES encrypted password. */
|
* supported, and return a DES encrypted password. */
|
||||||
if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13))
|
if (salt && salt[0] == '$' && strlen (cp) <= 13)
|
||||||
{
|
{
|
||||||
/*@observer@*/const char *method;
|
const char *method;
|
||||||
switch (salt[1])
|
switch (salt[1])
|
||||||
{
|
{
|
||||||
case '1':
|
case '1':
|
||||||
method = "MD5";
|
method = "MD5";
|
||||||
break;
|
break;
|
||||||
case '2':
|
|
||||||
method = "BCRYPT";
|
|
||||||
break;
|
|
||||||
case '5':
|
case '5':
|
||||||
method = "SHA256";
|
method = "SHA256";
|
||||||
break;
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
method = "SHA512";
|
method = "SHA512";
|
||||||
break;
|
break;
|
||||||
case 'y':
|
|
||||||
method = "YESCRYPT";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
static char nummethod[4] = "$x$";
|
static char nummethod[4] = "$x$";
|
||||||
@@ -62,18 +79,15 @@
|
|||||||
method = &nummethod[0];
|
method = &nummethod[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) fprintf (shadow_logfd,
|
fprintf (stderr,
|
||||||
_("crypt method not supported by libcrypt? (%s)\n"),
|
_("crypt method not supported by libcrypt? (%s)\n"),
|
||||||
method);
|
method);
|
||||||
exit (EXIT_FAILURE);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen (cp) != 13) {
|
if (strlen (cp) != 13)
|
||||||
return cp; /* nonstandard crypt() in libc, better bail out */
|
return cp; /* nonstandard crypt() in libc, better bail out */
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (cipher, cp);
|
strcpy (cipher, cp);
|
||||||
|
|
||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2008, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
void pw_entry (const char *name, struct passwd *pwent)
|
|
||||||
{
|
|
||||||
struct passwd *passwd;
|
|
||||||
|
|
||||||
struct spwd *spwd;
|
|
||||||
|
|
||||||
if (!(passwd = getpwnam (name))) { /* local, no need for xgetpwnam */
|
|
||||||
pwent->pw_name = NULL;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
pwent->pw_name = xstrdup (passwd->pw_name);
|
|
||||||
pwent->pw_uid = passwd->pw_uid;
|
|
||||||
pwent->pw_gid = passwd->pw_gid;
|
|
||||||
pwent->pw_gecos = xstrdup (passwd->pw_gecos);
|
|
||||||
pwent->pw_dir = xstrdup (passwd->pw_dir);
|
|
||||||
pwent->pw_shell = xstrdup (passwd->pw_shell);
|
|
||||||
#if !defined(AUTOSHADOW)
|
|
||||||
/* local, no need for xgetspnam */
|
|
||||||
if ((spwd = getspnam (name))) {
|
|
||||||
pwent->pw_passwd = xstrdup (spwd->sp_pwdp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
pwent->pw_passwd = xstrdup (passwd->pw_passwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1992, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1999, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
/*
|
|
||||||
* NEWENVP_STEP must be a power of two. This is the number
|
|
||||||
* of (char *) pointers to allocate at a time, to avoid using
|
|
||||||
* realloc() too often.
|
|
||||||
*/
|
|
||||||
#define NEWENVP_STEP 16
|
|
||||||
size_t newenvc = 0;
|
|
||||||
/*@null@*/char **newenvp = NULL;
|
|
||||||
|
|
||||||
static const char *const forbid[] = {
|
|
||||||
"_RLD_=",
|
|
||||||
"BASH_ENV=", /* GNU creeping featurism strikes again... */
|
|
||||||
"ENV=",
|
|
||||||
"HOME=",
|
|
||||||
"IFS=",
|
|
||||||
"KRB_CONF=",
|
|
||||||
"LD_", /* anything with the LD_ prefix */
|
|
||||||
"LIBPATH=",
|
|
||||||
"MAIL=",
|
|
||||||
"NLSPATH=",
|
|
||||||
"PATH=",
|
|
||||||
"SHELL=",
|
|
||||||
"SHLIB_PATH=",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* these are allowed, but with no slashes inside
|
|
||||||
(to work around security problems in GNU gettext) */
|
|
||||||
static const char *const noslash[] = {
|
|
||||||
"LANG=",
|
|
||||||
"LANGUAGE=",
|
|
||||||
"LC_", /* anything with the LC_ prefix */
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* initenv() must be called once before using addenv().
|
|
||||||
*/
|
|
||||||
void initenv (void)
|
|
||||||
{
|
|
||||||
newenvp = XMALLOC(NEWENVP_STEP, char *);
|
|
||||||
*newenvp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void addenv (const char *string, /*@null@*/const char *value)
|
|
||||||
{
|
|
||||||
char *cp, *newstring;
|
|
||||||
size_t i;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
if (NULL != value) {
|
|
||||||
size_t len = strlen (string) + strlen (value) + 2;
|
|
||||||
int wlen;
|
|
||||||
newstring = XMALLOC(len, char);
|
|
||||||
wlen = snprintf (newstring, len, "%s=%s", string, value);
|
|
||||||
assert (wlen == (int) len -1);
|
|
||||||
} else {
|
|
||||||
newstring = xstrdup (string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search for a '=' character within the string and if none is found
|
|
||||||
* just ignore the whole string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cp = strchr (newstring, '=');
|
|
||||||
if (NULL == cp) {
|
|
||||||
free (newstring);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = (size_t) (cp - newstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this environment variable is already set, change its value.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < newenvc; i++) {
|
|
||||||
if ( (strncmp (newstring, newenvp[i], n) == 0)
|
|
||||||
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < newenvc) {
|
|
||||||
free (newenvp[i]);
|
|
||||||
newenvp[i] = newstring;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Otherwise, save the new environment variable
|
|
||||||
*/
|
|
||||||
newenvp[newenvc++] = newstring;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* And extend the environment if needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether newenvc is a multiple of NEWENVP_STEP.
|
|
||||||
* If so we have to resize the vector.
|
|
||||||
* the expression (newenvc & (NEWENVP_STEP - 1)) == 0
|
|
||||||
* is equal to (newenvc % NEWENVP_STEP) == 0
|
|
||||||
* as long as NEWENVP_STEP is a power of 2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
|
|
||||||
bool update_environ;
|
|
||||||
char **__newenvp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the resize operation succeeds we can
|
|
||||||
* happily go on, else print a message.
|
|
||||||
*/
|
|
||||||
update_environ = (environ == newenvp);
|
|
||||||
|
|
||||||
__newenvp = REALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
|
|
||||||
|
|
||||||
if (NULL != __newenvp) {
|
|
||||||
/*
|
|
||||||
* If this is our current environment, update
|
|
||||||
* environ so that it doesn't point to some
|
|
||||||
* free memory area (realloc() could move it).
|
|
||||||
*/
|
|
||||||
if (update_environ)
|
|
||||||
environ = __newenvp;
|
|
||||||
newenvp = __newenvp;
|
|
||||||
} else {
|
|
||||||
(void) fputs (_("Environment overflow\n"), log_get_logfd());
|
|
||||||
newenvc--;
|
|
||||||
free (newenvp[newenvc]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The last entry of newenvp must be NULL
|
|
||||||
*/
|
|
||||||
|
|
||||||
newenvp[newenvc] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* set_env - copy command line arguments into the environment
|
|
||||||
*/
|
|
||||||
void set_env (int argc, char *const *argv)
|
|
||||||
{
|
|
||||||
int noname = 1;
|
|
||||||
char variable[1024];
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
for (; argc > 0; argc--, argv++) {
|
|
||||||
if (strlen (*argv) >= sizeof variable) {
|
|
||||||
continue; /* ignore long entries */
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = strchr (*argv, '=');
|
|
||||||
if (NULL == cp) {
|
|
||||||
int wlen;
|
|
||||||
wlen = snprintf (variable, sizeof variable, "L%d", noname);
|
|
||||||
assert (wlen < (int) sizeof(variable));
|
|
||||||
noname++;
|
|
||||||
addenv (variable, *argv);
|
|
||||||
} else {
|
|
||||||
const char *const *p;
|
|
||||||
|
|
||||||
for (p = forbid; NULL != *p; p++) {
|
|
||||||
if (strncmp (*argv, *p, strlen (*p)) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != *p) {
|
|
||||||
strncpy (variable, *argv, (size_t)(cp - *argv));
|
|
||||||
variable[cp - *argv] = '\0';
|
|
||||||
printf (_("You may not change $%s\n"),
|
|
||||||
variable);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
addenv (*argv, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sanitize_env - remove some nasty environment variables
|
|
||||||
* If you fall into a total paranoia, you should call this
|
|
||||||
* function for any root-setuid program or anything the user
|
|
||||||
* might change the environment with. 99% useless as almost
|
|
||||||
* all modern Unixes will handle setuid executables properly,
|
|
||||||
* but... I feel better with that silly precaution. -j.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void sanitize_env (void)
|
|
||||||
{
|
|
||||||
char **envp = environ;
|
|
||||||
const char *const *bad;
|
|
||||||
char **cur;
|
|
||||||
char **move;
|
|
||||||
|
|
||||||
for (cur = envp; NULL != *cur; cur++) {
|
|
||||||
for (bad = forbid; NULL != *bad; bad++) {
|
|
||||||
if (strncmp (*cur, *bad, strlen (*bad)) == 0) {
|
|
||||||
for (move = cur; NULL != *move; move++) {
|
|
||||||
*move = *(move + 1);
|
|
||||||
}
|
|
||||||
cur--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cur = envp; NULL != *cur; cur++) {
|
|
||||||
for (bad = noslash; NULL != *bad; bad++) {
|
|
||||||
if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strchr (*cur, '/') == NULL) {
|
|
||||||
continue; /* OK */
|
|
||||||
}
|
|
||||||
for (move = cur; NULL != *move; move++) {
|
|
||||||
*move = *(move + 1);
|
|
||||||
}
|
|
||||||
cur--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+26
-8
@@ -1,7 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2005 - 2006, Tomasz Kłoczko
|
* Copyright (c) 2005 - 2006, Tomasz Kłoczko
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
@@ -9,12 +32,7 @@
|
|||||||
/*
|
/*
|
||||||
* Exit codes used by shadow programs
|
* Exit codes used by shadow programs
|
||||||
*/
|
*/
|
||||||
#define E_SUCCESS EXIT_SUCCESS /* success */
|
#define E_SUCCESS 0 /* success */
|
||||||
/*
|
|
||||||
* FIXME: other values should differ from EXIT_FAILURE (and EXIT_SUCCESS).
|
|
||||||
*
|
|
||||||
* FIXME: reserve EXIT_FAILURE for internal failures.
|
|
||||||
*/
|
|
||||||
#define E_NOPERM 1 /* permission denied */
|
#define E_NOPERM 1 /* permission denied */
|
||||||
#define E_USAGE 2 /* invalid command syntax */
|
#define E_USAGE 2 /* invalid command syntax */
|
||||||
#define E_BAD_ARG 3 /* invalid argument to option */
|
#define E_BAD_ARG 3 /* invalid argument to option */
|
||||||
|
|||||||
+29
-6
@@ -1,9 +1,32 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 1997, Marek Michałkiewicz
|
* Copyright (c) 1996 - 1997, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
* Copyright (c) 2005 , Tomasz Kłoczko
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -22,8 +45,8 @@
|
|||||||
struct faillog {
|
struct faillog {
|
||||||
short fail_cnt; /* failures since last success */
|
short fail_cnt; /* failures since last success */
|
||||||
short fail_max; /* failures before turning account off */
|
short fail_max; /* failures before turning account off */
|
||||||
char fail_line[12]; /* last failure occurred here */
|
char fail_line[12]; /* last failure occured here */
|
||||||
time_t fail_time; /* last failure occurred then */
|
time_t fail_time; /* last failure occured then */
|
||||||
/*
|
/*
|
||||||
* If nonzero, the account will be re-enabled if there are no
|
* If nonzero, the account will be re-enabled if there are no
|
||||||
* failures for fail_locktime seconds since last failure.
|
* failures for fail_locktime seconds since last failure.
|
||||||
|
|||||||
-236
@@ -1,236 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2002 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2010, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "defines.h"
|
|
||||||
#include "faillog.h"
|
|
||||||
#include "failure.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#define YEAR (365L*DAY)
|
|
||||||
/*
|
|
||||||
* failure - make failure entry
|
|
||||||
*
|
|
||||||
* failure() creates a new (struct faillog) entry or updates an
|
|
||||||
* existing one with the current failed login information.
|
|
||||||
*/
|
|
||||||
void failure (uid_t uid, const char *tty, struct faillog *fl)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
off_t offset_uid = (off_t) (sizeof *fl) * uid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't do anything if failure logging isn't set up.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (access (FAILLOG_FILE, F_OK) != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open (FAILLOG_FILE, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
SYSLOG ((LOG_WARN,
|
|
||||||
"Can't write faillog entry for UID %lu in %s.",
|
|
||||||
(unsigned long) uid, FAILLOG_FILE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The file is indexed by UID value meaning that shared UID's
|
|
||||||
* share failure log records. That's OK since they really
|
|
||||||
* share just about everything else ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
|
||||||
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|
|
||||||
/* This is not necessarily a failure. The file is
|
|
||||||
* initially zero length.
|
|
||||||
*
|
|
||||||
* If lseek() or read() failed for any other reason, this
|
|
||||||
* might reset the counter. But the new failure will be
|
|
||||||
* logged.
|
|
||||||
*/
|
|
||||||
memzero (fl, sizeof *fl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the record. We increment the failure count to log the
|
|
||||||
* latest failure. The only concern here is overflow, and we'll
|
|
||||||
* check for that. The line name and time of day are both
|
|
||||||
* updated as well.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (fl->fail_cnt + 1 > 0) {
|
|
||||||
fl->fail_cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1);
|
|
||||||
(void) time (&fl->fail_time);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Seek back to the correct position in the file and write the
|
|
||||||
* record out. Ideally we should lock the file in case the same
|
|
||||||
* account is being logged simultaneously. But the risk doesn't
|
|
||||||
* seem that great.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
|
||||||
|| (write_full (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)
|
|
||||||
|| (close (fd) != 0)) {
|
|
||||||
SYSLOG ((LOG_WARN,
|
|
||||||
"Can't write faillog entry for UID %lu in %s.",
|
|
||||||
(unsigned long) uid, FAILLOG_FILE));
|
|
||||||
(void) close (fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool too_many_failures (const struct faillog *fl)
|
|
||||||
{
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
if ((0 == fl->fail_max) || (fl->fail_cnt < fl->fail_max)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == fl->fail_locktime) {
|
|
||||||
return true; /* locked until reset manually */
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) time (&now);
|
|
||||||
if ((fl->fail_time + fl->fail_locktime) < now) {
|
|
||||||
return false; /* enough time since last failure */
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* failcheck - check for failures > allowable
|
|
||||||
*
|
|
||||||
* failcheck() is called AFTER the password has been validated. If the
|
|
||||||
* account has been "attacked" with too many login failures, failcheck()
|
|
||||||
* returns 0 to indicate that the login should be denied even though
|
|
||||||
* the password is valid.
|
|
||||||
*
|
|
||||||
* failed indicates if the login failed AFTER the password has been
|
|
||||||
* validated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int failcheck (uid_t uid, struct faillog *fl, bool failed)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct faillog fail;
|
|
||||||
off_t offset_uid = (off_t) (sizeof *fl) * uid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Suppress the check if the log file isn't there.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (access (FAILLOG_FILE, F_OK) != 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open (FAILLOG_FILE, failed?O_RDONLY:O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
SYSLOG ((LOG_WARN,
|
|
||||||
"Can't open the faillog file (%s) to check UID %lu. "
|
|
||||||
"User access authorized.",
|
|
||||||
FAILLOG_FILE, (unsigned long) uid));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the record from the file and determine if the user has
|
|
||||||
* exceeded the failure limit. If "max" is zero, any number
|
|
||||||
* of failures are permitted. Only when "max" is non-zero and
|
|
||||||
* "cnt" is greater than or equal to "max" is the account
|
|
||||||
* considered to be locked.
|
|
||||||
*
|
|
||||||
* If read fails, there is no record for this user yet (the
|
|
||||||
* file is initially zero length and extended by writes), so
|
|
||||||
* no need to reset the count.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
|
||||||
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|
|
||||||
(void) close (fd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (too_many_failures (fl)) {
|
|
||||||
(void) close (fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The record is updated if this is not a failure. The count will
|
|
||||||
* be reset to zero, but the rest of the information will be left
|
|
||||||
* in the record in case someone wants to see where the failed
|
|
||||||
* login originated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!failed) {
|
|
||||||
fail = *fl;
|
|
||||||
fail.fail_cnt = 0;
|
|
||||||
|
|
||||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
|
||||||
|| (write_full (fd, &fail, sizeof fail) != (ssize_t) sizeof fail)
|
|
||||||
|| (close (fd) != 0)) {
|
|
||||||
SYSLOG ((LOG_WARN,
|
|
||||||
"Can't reset faillog entry for UID %lu in %s.",
|
|
||||||
(unsigned long) uid, FAILLOG_FILE));
|
|
||||||
(void) close (fd);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(void) close (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* failprint - print line of failure information
|
|
||||||
*
|
|
||||||
* failprint takes a (struct faillog) entry and formats it into a
|
|
||||||
* message which is displayed at login time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void failprint (const struct faillog *fail)
|
|
||||||
{
|
|
||||||
struct tm *tp;
|
|
||||||
char lasttimeb[256];
|
|
||||||
char *lasttime = lasttimeb;
|
|
||||||
time_t NOW;
|
|
||||||
|
|
||||||
if (0 == fail->fail_cnt) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp = localtime (&(fail->fail_time));
|
|
||||||
(void) time (&NOW);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print all information we have.
|
|
||||||
*/
|
|
||||||
(void) strftime (lasttimeb, sizeof lasttimeb, "%c", tp);
|
|
||||||
|
|
||||||
/*@-formatconst@*/
|
|
||||||
(void) printf (ngettext ("%d failure since last login.\n"
|
|
||||||
"Last was %s on %s.\n",
|
|
||||||
"%d failures since last login.\n"
|
|
||||||
"Last was %s on %s.\n",
|
|
||||||
(unsigned long) fail->fail_cnt),
|
|
||||||
fail->fail_cnt, lasttime, fail->fail_line);
|
|
||||||
/*@=formatconst@*/
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1997 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* $Id$ */
|
|
||||||
#ifndef _FAILURE_H_
|
|
||||||
#define _FAILURE_H_
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "faillog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* failure - make failure entry
|
|
||||||
*
|
|
||||||
* failure() creates a new (struct faillog) entry or updates an
|
|
||||||
* existing one with the current failed login information.
|
|
||||||
*/
|
|
||||||
extern void failure (uid_t, const char *, struct faillog *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* failcheck - check for failures > allowable
|
|
||||||
*
|
|
||||||
* failcheck() is called AFTER the password has been validated. If the
|
|
||||||
* account has been "attacked" with too many login failures, failcheck()
|
|
||||||
* returns FALSE to indicate that the login should be denied even though
|
|
||||||
* the password is valid.
|
|
||||||
*/
|
|
||||||
extern int failcheck (uid_t uid, struct faillog *fl, bool failed);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* failprint - print line of failure information
|
|
||||||
*
|
|
||||||
* failprint takes a (struct faillog) entry and formats it into a
|
|
||||||
* message which is displayed at login time.
|
|
||||||
*/
|
|
||||||
extern void failprint (const struct faillog *);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-105
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 , Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 1997, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* valid_field - insure that a field contains all legal characters
|
|
||||||
*
|
|
||||||
* The supplied field is scanned for non-printable and other illegal
|
|
||||||
* characters.
|
|
||||||
* + -1 is returned if an illegal or control character is present.
|
|
||||||
* + 1 is returned if no illegal or control characters are present,
|
|
||||||
* but the field contains a non-printable character.
|
|
||||||
* + 0 is returned otherwise.
|
|
||||||
*/
|
|
||||||
int valid_field (const char *field, const char *illegal)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (NULL == field) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For each character of field, search if it appears in the list
|
|
||||||
* of illegal characters. */
|
|
||||||
if (illegal && NULL != strpbrk (field, illegal)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search if there are non-printable or control characters */
|
|
||||||
for (cp = field; '\0' != *cp; cp++) {
|
|
||||||
unsigned char c = *cp;
|
|
||||||
if (!isprint (c)) {
|
|
||||||
err = 1;
|
|
||||||
}
|
|
||||||
if (iscntrl (c)) {
|
|
||||||
err = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* change_field - change a single field if a new value is given.
|
|
||||||
*
|
|
||||||
* prompt the user with the name of the field being changed and the
|
|
||||||
* current value.
|
|
||||||
*/
|
|
||||||
void change_field (char *buf, size_t maxsize, const char *prompt)
|
|
||||||
{
|
|
||||||
char newf[200];
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
if (maxsize > sizeof (newf)) {
|
|
||||||
maxsize = sizeof (newf);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("\t%s [%s]: ", prompt, buf);
|
|
||||||
(void) fflush (stdout);
|
|
||||||
if (fgets (newf, maxsize, stdin) != newf) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = strchr (newf, '\n');
|
|
||||||
if (NULL == cp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*cp = '\0';
|
|
||||||
|
|
||||||
if ('\0' != newf[0]) {
|
|
||||||
/*
|
|
||||||
* Remove leading and trailing whitespace. This also
|
|
||||||
* makes it possible to change the field to empty, by
|
|
||||||
* entering a space. --marekm
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (newf < cp && isspace (cp[-1])) {
|
|
||||||
cp--;
|
|
||||||
}
|
|
||||||
*cp = '\0';
|
|
||||||
|
|
||||||
cp = newf;
|
|
||||||
while (isspace (*cp)) {
|
|
||||||
cp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (buf, cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,500 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2011, Nicolas François
|
|
||||||
* SPDX-FileCopyrightText: 2014, Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "groupio.h"
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get_ranges - Get the minimum and maximum ID ranges for the search
|
|
||||||
*
|
|
||||||
* This function will return the minimum and maximum ranges for IDs
|
|
||||||
*
|
|
||||||
* 0: The function completed successfully
|
|
||||||
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
|
|
||||||
*
|
|
||||||
* preferred_min: The special-case minimum value for a specifically-
|
|
||||||
* requested ID, which may be lower than the standard min_id
|
|
||||||
*/
|
|
||||||
static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
|
|
||||||
gid_t *preferred_min)
|
|
||||||
{
|
|
||||||
gid_t gid_def_max = 0;
|
|
||||||
|
|
||||||
if (sys_group) {
|
|
||||||
/* System groups */
|
|
||||||
|
|
||||||
/* A requested ID is allowed to be below the autoselect range */
|
|
||||||
*preferred_min = (gid_t) 1;
|
|
||||||
|
|
||||||
/* Get the minimum ID range from login.defs or default to 101 */
|
|
||||||
*min_id = getdef_ulong ("SYS_GID_MIN", 101UL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If SYS_GID_MAX is unspecified, we should assume it to be one
|
|
||||||
* less than the GID_MIN (which is reserved for non-system accounts)
|
|
||||||
*/
|
|
||||||
gid_def_max = getdef_ulong ("GID_MIN", 1000UL) - 1;
|
|
||||||
*max_id = getdef_ulong ("SYS_GID_MAX", gid_def_max);
|
|
||||||
|
|
||||||
/* Check that the ranges make sense */
|
|
||||||
if (*max_id < *min_id) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
|
|
||||||
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
|
|
||||||
log_get_progname(), (unsigned long) *min_id,
|
|
||||||
getdef_ulong ("GID_MIN", 1000UL),
|
|
||||||
(unsigned long) *max_id);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Zero is reserved for root and the allocation algorithm does not
|
|
||||||
* work right with it.
|
|
||||||
*/
|
|
||||||
if (*min_id == 0) {
|
|
||||||
*min_id = (gid_t) 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Non-system groups */
|
|
||||||
|
|
||||||
/* Get the values from login.defs or use reasonable defaults */
|
|
||||||
*min_id = getdef_ulong ("GID_MIN", 1000UL);
|
|
||||||
*max_id = getdef_ulong ("GID_MAX", 60000UL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The preferred minimum should match the standard ID minimum
|
|
||||||
* for non-system groups.
|
|
||||||
*/
|
|
||||||
*preferred_min = *min_id;
|
|
||||||
|
|
||||||
/* Check that the ranges make sense */
|
|
||||||
if (*max_id < *min_id) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: GID_MIN (%lu), "
|
|
||||||
"GID_MAX (%lu)\n"),
|
|
||||||
log_get_progname(), (unsigned long) *min_id,
|
|
||||||
(unsigned long) *max_id);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check_gid - See if the requested GID is available
|
|
||||||
*
|
|
||||||
* On success, return 0
|
|
||||||
* If the ID is in use, return EEXIST
|
|
||||||
* If the ID might clash with -1, return EINVAL
|
|
||||||
* If the ID is outside the range, return ERANGE
|
|
||||||
* In other cases, return errno from getgrgid()
|
|
||||||
*/
|
|
||||||
static int check_gid (const gid_t gid,
|
|
||||||
const gid_t gid_min,
|
|
||||||
const gid_t gid_max,
|
|
||||||
const bool *used_gids)
|
|
||||||
{
|
|
||||||
/* First test that the preferred ID is in the range */
|
|
||||||
if (gid < gid_min || gid > gid_max) {
|
|
||||||
return ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for compatibility with 16b and 32b gid_t error codes */
|
|
||||||
if (gid == UINT16_MAX || gid == UINT32_MAX) {
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether we already detected this GID
|
|
||||||
* using the gr_next() loop
|
|
||||||
*/
|
|
||||||
if (used_gids != NULL && used_gids[gid]) {
|
|
||||||
return EEXIST;
|
|
||||||
}
|
|
||||||
/* Check if the GID exists according to NSS */
|
|
||||||
errno = 0;
|
|
||||||
if (prefix_getgrgid (gid) != NULL) {
|
|
||||||
return EEXIST;
|
|
||||||
} else {
|
|
||||||
/* getgrgid() was NULL
|
|
||||||
* we have to ignore errors as temporary
|
|
||||||
* failures of remote user identity services
|
|
||||||
* would completely block user/group creation
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we've made it here, the GID must be available */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find_new_gid - Find a new unused GID.
|
|
||||||
*
|
|
||||||
* If successful, find_new_gid provides an unused group ID in the
|
|
||||||
* [GID_MIN:GID_MAX] range.
|
|
||||||
* This ID should be higher than all the used GID, but if not possible,
|
|
||||||
* the lowest unused ID in the range will be returned.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 if no unused GIDs are available.
|
|
||||||
*/
|
|
||||||
int find_new_gid (bool sys_group,
|
|
||||||
gid_t *gid,
|
|
||||||
/*@null@*/gid_t const *preferred_gid)
|
|
||||||
{
|
|
||||||
bool *used_gids;
|
|
||||||
const struct group *grp;
|
|
||||||
gid_t gid_min, gid_max, preferred_min;
|
|
||||||
gid_t id;
|
|
||||||
gid_t lowest_found, highest_found;
|
|
||||||
int result;
|
|
||||||
int nospam = 0;
|
|
||||||
|
|
||||||
assert(gid != NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, figure out what ID range is appropriate for
|
|
||||||
* automatic assignment
|
|
||||||
*/
|
|
||||||
result = get_ranges (sys_group, &gid_min, &gid_max, &preferred_min);
|
|
||||||
if (result == EINVAL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the preferred GID is available */
|
|
||||||
if (preferred_gid) {
|
|
||||||
result = check_gid (*preferred_gid, preferred_min, gid_max, NULL);
|
|
||||||
if (result == 0) {
|
|
||||||
/*
|
|
||||||
* Make sure the GID isn't queued for use already
|
|
||||||
*/
|
|
||||||
if (gr_locate_gid (*preferred_gid) == NULL) {
|
|
||||||
*gid = *preferred_gid;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* gr_locate_gid() found the GID in an as-yet uncommitted
|
|
||||||
* entry. We'll proceed below and auto-set a GID.
|
|
||||||
*/
|
|
||||||
} else if (result == EEXIST || result == ERANGE || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* Continue on below. At this time, we won't
|
|
||||||
* treat these three cases differently.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred. We should report
|
|
||||||
* this and fail the group creation.
|
|
||||||
* This differs from the automatic creation
|
|
||||||
* behavior below, since if a specific GID was
|
|
||||||
* requested and generated an error, the user is
|
|
||||||
* more likely to want to stop and address the
|
|
||||||
* issue.
|
|
||||||
*/
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Encountered error attempting to use "
|
|
||||||
"preferred GID: %s\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search the entire group file,
|
|
||||||
* looking for the next unused value.
|
|
||||||
*
|
|
||||||
* We first check the local database with gr_rewind/gr_next to find
|
|
||||||
* all local values that are in use.
|
|
||||||
*
|
|
||||||
* We then compare the next free value to all databases (local and
|
|
||||||
* remote) and iterate until we find a free one. If there are free
|
|
||||||
* values beyond the lowest (system groups) or highest (non-system
|
|
||||||
* groups), we will prefer those and avoid potentially reclaiming a
|
|
||||||
* deleted group (which can be a security issue, since it may grant
|
|
||||||
* access to files belonging to that former group).
|
|
||||||
*
|
|
||||||
* If there are no GIDs available at the end of the search, we will
|
|
||||||
* have no choice but to iterate through the range looking for gaps.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Create an array to hold all of the discovered GIDs */
|
|
||||||
used_gids = CALLOC (gid_max + 1, bool);
|
|
||||||
if (NULL == used_gids) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to allocate memory: %s\n"),
|
|
||||||
log_get_progname(), strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First look for the lowest and highest value in the local database */
|
|
||||||
(void) gr_rewind ();
|
|
||||||
highest_found = gid_min;
|
|
||||||
lowest_found = gid_max;
|
|
||||||
while ((grp = gr_next ()) != NULL) {
|
|
||||||
/*
|
|
||||||
* Does this entry have a lower GID than the lowest we've found
|
|
||||||
* so far?
|
|
||||||
*/
|
|
||||||
if ((grp->gr_gid <= lowest_found) && (grp->gr_gid >= gid_min)) {
|
|
||||||
lowest_found = grp->gr_gid - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does this entry have a higher GID than the highest we've found
|
|
||||||
* so far?
|
|
||||||
*/
|
|
||||||
if ((grp->gr_gid >= highest_found) && (grp->gr_gid <= gid_max)) {
|
|
||||||
highest_found = grp->gr_gid + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create index of used GIDs */
|
|
||||||
if (grp->gr_gid >= gid_min
|
|
||||||
&& grp->gr_gid <= gid_max) {
|
|
||||||
|
|
||||||
used_gids[grp->gr_gid] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sys_group) {
|
|
||||||
/*
|
|
||||||
* For system groups, we want to start from the
|
|
||||||
* top of the range and work downwards.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At the conclusion of the gr_next() search, we will either
|
|
||||||
* have a presumed-free GID or we will be at GID_MIN - 1.
|
|
||||||
*/
|
|
||||||
if (lowest_found < gid_min) {
|
|
||||||
/*
|
|
||||||
* In this case, a GID is in use at GID_MIN.
|
|
||||||
*
|
|
||||||
* We will reset the search to GID_MAX and proceed down
|
|
||||||
* through all the GIDs (skipping those we detected with
|
|
||||||
* used_gids) for a free one. It is a known issue that
|
|
||||||
* this may result in reusing a previously-deleted GID,
|
|
||||||
* so administrators should be instructed to use this
|
|
||||||
* auto-detection with care (and prefer to assign GIDs
|
|
||||||
* explicitly).
|
|
||||||
*/
|
|
||||||
lowest_found = gid_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through all of the IDs in the range */
|
|
||||||
for (id = lowest_found; id >= gid_min; id--) {
|
|
||||||
result = check_gid (id, gid_min, gid_max, used_gids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This GID is available. Return it. */
|
|
||||||
*gid = id;
|
|
||||||
free (used_gids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique system GID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available GIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later GID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we get all the way through the loop, try again from GID_MAX,
|
|
||||||
* unless that was where we previously started. (NOTE: the worst-case
|
|
||||||
* scenario here is that we will run through (GID_MAX - GID_MIN - 1)
|
|
||||||
* cycles *again* if we fall into this case with lowest_found as
|
|
||||||
* GID_MAX - 1, all groups in the range in use and maintained by
|
|
||||||
* network services such as LDAP.)
|
|
||||||
*/
|
|
||||||
if (lowest_found != gid_max) {
|
|
||||||
for (id = gid_max; id >= gid_min; id--) {
|
|
||||||
result = check_gid (id, gid_min, gid_max, used_gids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This GID is available. Return it. */
|
|
||||||
*gid = id;
|
|
||||||
free (used_gids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique system GID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available GIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later GID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* !sys_group */
|
|
||||||
/*
|
|
||||||
* For non-system groups, we want to start from the
|
|
||||||
* bottom of the range and work upwards.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At the conclusion of the gr_next() search, we will either
|
|
||||||
* have a presumed-free GID or we will be at GID_MAX + 1.
|
|
||||||
*/
|
|
||||||
if (highest_found > gid_max) {
|
|
||||||
/*
|
|
||||||
* In this case, a GID is in use at GID_MAX.
|
|
||||||
*
|
|
||||||
* We will reset the search to GID_MIN and proceed up
|
|
||||||
* through all the GIDs (skipping those we detected with
|
|
||||||
* used_gids) for a free one. It is a known issue that
|
|
||||||
* this may result in reusing a previously-deleted GID,
|
|
||||||
* so administrators should be instructed to use this
|
|
||||||
* auto-detection with care (and prefer to assign GIDs
|
|
||||||
* explicitly).
|
|
||||||
*/
|
|
||||||
highest_found = gid_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through all of the IDs in the range */
|
|
||||||
for (id = highest_found; id <= gid_max; id++) {
|
|
||||||
result = check_gid (id, gid_min, gid_max, used_gids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This GID is available. Return it. */
|
|
||||||
*gid = id;
|
|
||||||
free (used_gids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique GID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available GIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later GID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we get all the way through the loop, try again from GID_MIN,
|
|
||||||
* unless that was where we previously started. (NOTE: the worst-case
|
|
||||||
* scenario here is that we will run through (GID_MAX - GID_MIN - 1)
|
|
||||||
* cycles *again* if we fall into this case with highest_found as
|
|
||||||
* GID_MIN + 1, all groups in the range in use and maintained by
|
|
||||||
* network services such as LDAP.)
|
|
||||||
*/
|
|
||||||
if (highest_found != gid_min) {
|
|
||||||
for (id = gid_min; id <= gid_max; id++) {
|
|
||||||
result = check_gid (id, gid_min, gid_max, used_gids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This GID is available. Return it. */
|
|
||||||
*gid = id;
|
|
||||||
free (used_gids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique GID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available GIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later GID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The code reached here and found no available IDs in the range */
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique GID (no more available GIDs)\n"),
|
|
||||||
log_get_progname());
|
|
||||||
SYSLOG ((LOG_WARN, "no more available GIDs on the system"));
|
|
||||||
free (used_gids);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2012 Eric Biederman
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ifdef ENABLE_SUBIDS
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "subordinateio.h"
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find_new_sub_gids - Find a new unused range of GIDs.
|
|
||||||
*
|
|
||||||
* If successful, find_new_sub_gids provides a range of unused
|
|
||||||
* user IDs in the [SUB_GID_MIN:SUB_GID_MAX] range.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 if no unused GIDs are available.
|
|
||||||
*/
|
|
||||||
int find_new_sub_gids (gid_t *range_start, unsigned long *range_count)
|
|
||||||
{
|
|
||||||
unsigned long min, max;
|
|
||||||
unsigned long count;
|
|
||||||
gid_t start;
|
|
||||||
|
|
||||||
assert (range_start != NULL);
|
|
||||||
assert (range_count != NULL);
|
|
||||||
|
|
||||||
min = getdef_ulong ("SUB_GID_MIN", 100000UL);
|
|
||||||
max = getdef_ulong ("SUB_GID_MAX", 600100000UL);
|
|
||||||
count = getdef_ulong ("SUB_GID_COUNT", 65536);
|
|
||||||
|
|
||||||
if (min > max || count >= max || (min + count - 1) > max) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: SUB_GID_MIN (%lu),"
|
|
||||||
" SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"),
|
|
||||||
log_get_progname(), min, max, count);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = sub_gid_find_free_range(min, max, count);
|
|
||||||
if (start == (gid_t)-1) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique subordinate GID range\n"),
|
|
||||||
log_get_progname());
|
|
||||||
SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*range_start = start;
|
|
||||||
*range_count = count;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else /* !ENABLE_SUBIDS */
|
|
||||||
extern int ISO_C_forbids_an_empty_translation_unit;
|
|
||||||
#endif /* !ENABLE_SUBIDS */
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2012 Eric Biederman
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ifdef ENABLE_SUBIDS
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "subordinateio.h"
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find_new_sub_uids - Find a new unused range of UIDs.
|
|
||||||
*
|
|
||||||
* If successful, find_new_sub_uids provides a range of unused
|
|
||||||
* user IDs in the [SUB_UID_MIN:SUB_UID_MAX] range.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 if no unused UIDs are available.
|
|
||||||
*/
|
|
||||||
int find_new_sub_uids (uid_t *range_start, unsigned long *range_count)
|
|
||||||
{
|
|
||||||
unsigned long min, max;
|
|
||||||
unsigned long count;
|
|
||||||
uid_t start;
|
|
||||||
|
|
||||||
assert (range_start != NULL);
|
|
||||||
assert (range_count != NULL);
|
|
||||||
|
|
||||||
min = getdef_ulong ("SUB_UID_MIN", 100000UL);
|
|
||||||
max = getdef_ulong ("SUB_UID_MAX", 600100000UL);
|
|
||||||
count = getdef_ulong ("SUB_UID_COUNT", 65536);
|
|
||||||
|
|
||||||
if (min > max || count >= max || (min + count - 1) > max) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: SUB_UID_MIN (%lu),"
|
|
||||||
" SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"),
|
|
||||||
log_get_progname(), min, max, count);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = sub_uid_find_free_range(min, max, count);
|
|
||||||
if (start == (uid_t)-1) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique subordinate UID range\n"),
|
|
||||||
log_get_progname());
|
|
||||||
SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*range_start = start;
|
|
||||||
*range_count = count;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else /* !ENABLE_SUBIDS */
|
|
||||||
extern int ISO_C_forbids_an_empty_translation_unit;
|
|
||||||
#endif /* !ENABLE_SUBIDS */
|
|
||||||
|
|
||||||
@@ -1,501 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 2008 - 2011, Nicolas François
|
|
||||||
* SPDX-FileCopyrightText: 2014, Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "pwio.h"
|
|
||||||
#include "getdef.h"
|
|
||||||
#include "shadowlog.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get_ranges - Get the minimum and maximum ID ranges for the search
|
|
||||||
*
|
|
||||||
* This function will return the minimum and maximum ranges for IDs
|
|
||||||
*
|
|
||||||
* 0: The function completed successfully
|
|
||||||
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
|
|
||||||
*
|
|
||||||
* preferred_min: The special-case minimum value for a specifically-
|
|
||||||
* requested ID, which may be lower than the standard min_id
|
|
||||||
*/
|
|
||||||
static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
|
|
||||||
uid_t *preferred_min)
|
|
||||||
{
|
|
||||||
uid_t uid_def_max = 0;
|
|
||||||
|
|
||||||
if (sys_user) {
|
|
||||||
/* System users */
|
|
||||||
|
|
||||||
/* A requested ID is allowed to be below the autoselect range */
|
|
||||||
*preferred_min = (uid_t) 1;
|
|
||||||
|
|
||||||
/* Get the minimum ID range from login.defs or default to 101 */
|
|
||||||
*min_id = getdef_ulong ("SYS_UID_MIN", 101UL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If SYS_UID_MAX is unspecified, we should assume it to be one
|
|
||||||
* less than the UID_MIN (which is reserved for non-system accounts)
|
|
||||||
*/
|
|
||||||
uid_def_max = getdef_ulong ("UID_MIN", 1000UL) - 1;
|
|
||||||
*max_id = getdef_ulong ("SYS_UID_MAX", uid_def_max);
|
|
||||||
|
|
||||||
/* Check that the ranges make sense */
|
|
||||||
if (*max_id < *min_id) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
|
|
||||||
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
|
|
||||||
log_get_progname(), (unsigned long) *min_id,
|
|
||||||
getdef_ulong ("UID_MIN", 1000UL),
|
|
||||||
(unsigned long) *max_id);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Zero is reserved for root and the allocation algorithm does not
|
|
||||||
* work right with it.
|
|
||||||
*/
|
|
||||||
if (*min_id == 0) {
|
|
||||||
*min_id = (uid_t) 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Non-system users */
|
|
||||||
|
|
||||||
/* Get the values from login.defs or use reasonable defaults */
|
|
||||||
*min_id = getdef_ulong ("UID_MIN", 1000UL);
|
|
||||||
*max_id = getdef_ulong ("UID_MAX", 60000UL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The preferred minimum should match the standard ID minimum
|
|
||||||
* for non-system users.
|
|
||||||
*/
|
|
||||||
*preferred_min = *min_id;
|
|
||||||
|
|
||||||
/* Check that the ranges make sense */
|
|
||||||
if (*max_id < *min_id) {
|
|
||||||
(void) fprintf (log_get_logfd(),
|
|
||||||
_("%s: Invalid configuration: UID_MIN (%lu), "
|
|
||||||
"UID_MAX (%lu)\n"),
|
|
||||||
log_get_progname(), (unsigned long) *min_id,
|
|
||||||
(unsigned long) *max_id);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check_uid - See if the requested UID is available
|
|
||||||
*
|
|
||||||
* On success, return 0
|
|
||||||
* If the ID is in use, return EEXIST
|
|
||||||
* If the ID might clash with -1, return EINVAL
|
|
||||||
* If the ID is outside the range, return ERANGE
|
|
||||||
* In other cases, return errno from getpwuid()
|
|
||||||
*/
|
|
||||||
static int check_uid(const uid_t uid,
|
|
||||||
const uid_t uid_min,
|
|
||||||
const uid_t uid_max,
|
|
||||||
const bool *used_uids)
|
|
||||||
{
|
|
||||||
/* First test that the preferred ID is in the range */
|
|
||||||
if (uid < uid_min || uid > uid_max) {
|
|
||||||
return ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for compatibility with 16b and 32b uid_t error codes */
|
|
||||||
if (uid == UINT16_MAX || uid == UINT32_MAX) {
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether we already detected this UID
|
|
||||||
* using the pw_next() loop
|
|
||||||
*/
|
|
||||||
if (used_uids != NULL && used_uids[uid]) {
|
|
||||||
return EEXIST;
|
|
||||||
}
|
|
||||||
/* Check if the UID exists according to NSS */
|
|
||||||
errno = 0;
|
|
||||||
if (prefix_getpwuid(uid) != NULL) {
|
|
||||||
return EEXIST;
|
|
||||||
} else {
|
|
||||||
/* getpwuid() was NULL
|
|
||||||
* we have to ignore errors as temporary
|
|
||||||
* failures of remote user identity services
|
|
||||||
* would completely block user/group creation
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we've made it here, the UID must be available */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find_new_uid - Find a new unused UID.
|
|
||||||
*
|
|
||||||
* If successful, find_new_uid provides an unused user ID in the
|
|
||||||
* [UID_MIN:UID_MAX] range.
|
|
||||||
* This ID should be higher than all the used UID, but if not possible,
|
|
||||||
* the lowest unused ID in the range will be returned.
|
|
||||||
*
|
|
||||||
* Return 0 on success, -1 if no unused UIDs are available.
|
|
||||||
*/
|
|
||||||
int find_new_uid(bool sys_user,
|
|
||||||
uid_t *uid,
|
|
||||||
/*@null@*/uid_t const *preferred_uid)
|
|
||||||
{
|
|
||||||
bool *used_uids;
|
|
||||||
const struct passwd *pwd;
|
|
||||||
uid_t uid_min, uid_max, preferred_min;
|
|
||||||
uid_t id;
|
|
||||||
uid_t lowest_found, highest_found;
|
|
||||||
int result;
|
|
||||||
int nospam = 0;
|
|
||||||
|
|
||||||
assert (uid != NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, figure out what ID range is appropriate for
|
|
||||||
* automatic assignment
|
|
||||||
*/
|
|
||||||
result = get_ranges (sys_user, &uid_min, &uid_max, &preferred_min);
|
|
||||||
if (result == EINVAL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the preferred UID is available */
|
|
||||||
if (preferred_uid) {
|
|
||||||
result = check_uid (*preferred_uid, preferred_min, uid_max, NULL);
|
|
||||||
if (result == 0) {
|
|
||||||
/*
|
|
||||||
* Make sure the UID isn't queued for use already
|
|
||||||
*/
|
|
||||||
if (pw_locate_uid (*preferred_uid) == NULL) {
|
|
||||||
*uid = *preferred_uid;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* pw_locate_uid() found the UID in an as-yet uncommitted
|
|
||||||
* entry. We'll proceed below and auto-set an UID.
|
|
||||||
*/
|
|
||||||
} else if (result == EEXIST || result == ERANGE || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* Continue on below. At this time, we won't
|
|
||||||
* treat these three cases differently.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred. We should report
|
|
||||||
* this and fail the user creation.
|
|
||||||
* This differs from the automatic creation
|
|
||||||
* behavior below, since if a specific UID was
|
|
||||||
* requested and generated an error, the user is
|
|
||||||
* more likely to want to stop and address the
|
|
||||||
* issue.
|
|
||||||
*/
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Encountered error attempting to use "
|
|
||||||
"preferred UID: %s\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search the entire passwd file,
|
|
||||||
* looking for the next unused value.
|
|
||||||
*
|
|
||||||
* We first check the local database with pw_rewind/pw_next to find
|
|
||||||
* all local values that are in use.
|
|
||||||
*
|
|
||||||
* We then compare the next free value to all databases (local and
|
|
||||||
* remote) and iterate until we find a free one. If there are free
|
|
||||||
* values beyond the lowest (system users) or highest (non-system
|
|
||||||
* users), we will prefer those and avoid potentially reclaiming a
|
|
||||||
* deleted user (which can be a security issue, since it may grant
|
|
||||||
* access to files belonging to that former user).
|
|
||||||
*
|
|
||||||
* If there are no UIDs available at the end of the search, we will
|
|
||||||
* have no choice but to iterate through the range looking for gaps.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Create an array to hold all of the discovered UIDs */
|
|
||||||
used_uids = MALLOC(uid_max + 1, bool);
|
|
||||||
if (NULL == used_uids) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: failed to allocate memory: %s\n"),
|
|
||||||
log_get_progname(), strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset (used_uids, false, sizeof (bool) * (uid_max + 1));
|
|
||||||
|
|
||||||
/* First look for the lowest and highest value in the local database */
|
|
||||||
(void) pw_rewind ();
|
|
||||||
highest_found = uid_min;
|
|
||||||
lowest_found = uid_max;
|
|
||||||
while ((pwd = pw_next ()) != NULL) {
|
|
||||||
/*
|
|
||||||
* Does this entry have a lower UID than the lowest we've found
|
|
||||||
* so far?
|
|
||||||
*/
|
|
||||||
if ((pwd->pw_uid <= lowest_found) && (pwd->pw_uid >= uid_min)) {
|
|
||||||
lowest_found = pwd->pw_uid - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does this entry have a higher UID than the highest we've found
|
|
||||||
* so far?
|
|
||||||
*/
|
|
||||||
if ((pwd->pw_uid >= highest_found) && (pwd->pw_uid <= uid_max)) {
|
|
||||||
highest_found = pwd->pw_uid + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create index of used UIDs */
|
|
||||||
if (pwd->pw_uid >= uid_min
|
|
||||||
&& pwd->pw_uid <= uid_max) {
|
|
||||||
|
|
||||||
used_uids[pwd->pw_uid] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sys_user) {
|
|
||||||
/*
|
|
||||||
* For system users, we want to start from the
|
|
||||||
* top of the range and work downwards.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At the conclusion of the pw_next() search, we will either
|
|
||||||
* have a presumed-free UID or we will be at UID_MIN - 1.
|
|
||||||
*/
|
|
||||||
if (lowest_found < uid_min) {
|
|
||||||
/*
|
|
||||||
* In this case, an UID is in use at UID_MIN.
|
|
||||||
*
|
|
||||||
* We will reset the search to UID_MAX and proceed down
|
|
||||||
* through all the UIDs (skipping those we detected with
|
|
||||||
* used_uids) for a free one. It is a known issue that
|
|
||||||
* this may result in reusing a previously-deleted UID,
|
|
||||||
* so administrators should be instructed to use this
|
|
||||||
* auto-detection with care (and prefer to assign UIDs
|
|
||||||
* explicitly).
|
|
||||||
*/
|
|
||||||
lowest_found = uid_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through all of the IDs in the range */
|
|
||||||
for (id = lowest_found; id >= uid_min; id--) {
|
|
||||||
result = check_uid (id, uid_min, uid_max, used_uids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This UID is available. Return it. */
|
|
||||||
*uid = id;
|
|
||||||
free (used_uids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique system UID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available UIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later UID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we get all the way through the loop, try again from UID_MAX,
|
|
||||||
* unless that was where we previously started. (NOTE: the worst-case
|
|
||||||
* scenario here is that we will run through (UID_MAX - UID_MIN - 1)
|
|
||||||
* cycles *again* if we fall into this case with lowest_found as
|
|
||||||
* UID_MAX - 1, all users in the range in use and maintained by
|
|
||||||
* network services such as LDAP.)
|
|
||||||
*/
|
|
||||||
if (lowest_found != uid_max) {
|
|
||||||
for (id = uid_max; id >= uid_min; id--) {
|
|
||||||
result = check_uid (id, uid_min, uid_max, used_uids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This UID is available. Return it. */
|
|
||||||
*uid = id;
|
|
||||||
free (used_uids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique system UID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG((LOG_ERR,
|
|
||||||
"Error checking available UIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later UID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* !sys_user */
|
|
||||||
/*
|
|
||||||
* For non-system users, we want to start from the
|
|
||||||
* bottom of the range and work upwards.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At the conclusion of the pw_next() search, we will either
|
|
||||||
* have a presumed-free UID or we will be at UID_MAX + 1.
|
|
||||||
*/
|
|
||||||
if (highest_found > uid_max) {
|
|
||||||
/*
|
|
||||||
* In this case, a UID is in use at UID_MAX.
|
|
||||||
*
|
|
||||||
* We will reset the search to UID_MIN and proceed up
|
|
||||||
* through all the UIDs (skipping those we detected with
|
|
||||||
* used_uids) for a free one. It is a known issue that
|
|
||||||
* this may result in reusing a previously-deleted UID,
|
|
||||||
* so administrators should be instructed to use this
|
|
||||||
* auto-detection with care (and prefer to assign UIDs
|
|
||||||
* explicitly).
|
|
||||||
*/
|
|
||||||
highest_found = uid_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through all of the IDs in the range */
|
|
||||||
for (id = highest_found; id <= uid_max; id++) {
|
|
||||||
result = check_uid (id, uid_min, uid_max, used_uids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This UID is available. Return it. */
|
|
||||||
*uid = id;
|
|
||||||
free (used_uids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique UID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available UIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later UID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we get all the way through the loop, try again from UID_MIN,
|
|
||||||
* unless that was where we previously started. (NOTE: the worst-case
|
|
||||||
* scenario here is that we will run through (UID_MAX - UID_MIN - 1)
|
|
||||||
* cycles *again* if we fall into this case with highest_found as
|
|
||||||
* UID_MIN + 1, all users in the range in use and maintained by
|
|
||||||
* network services such as LDAP.)
|
|
||||||
*/
|
|
||||||
if (highest_found != uid_min) {
|
|
||||||
for (id = uid_min; id <= uid_max; id++) {
|
|
||||||
result = check_uid (id, uid_min, uid_max, used_uids);
|
|
||||||
if (result == 0) {
|
|
||||||
/* This UID is available. Return it. */
|
|
||||||
*uid = id;
|
|
||||||
free (used_uids);
|
|
||||||
return 0;
|
|
||||||
} else if (result == EEXIST || result == EINVAL) {
|
|
||||||
/*
|
|
||||||
* This GID is in use or unusable, we'll
|
|
||||||
* continue to the next.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* An unexpected error occurred.
|
|
||||||
*
|
|
||||||
* Only report it the first time to avoid spamming
|
|
||||||
* the logs
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (!nospam) {
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique UID (%s). "
|
|
||||||
"Suppressing additional messages.\n"),
|
|
||||||
log_get_progname(), strerror (result));
|
|
||||||
SYSLOG ((LOG_ERR,
|
|
||||||
"Error checking available UIDs: %s",
|
|
||||||
strerror (result)));
|
|
||||||
nospam = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We will continue anyway. Hopefully a later UID
|
|
||||||
* will work properly.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The code reached here and found no available IDs in the range */
|
|
||||||
fprintf (log_get_logfd(),
|
|
||||||
_("%s: Can't get unique UID (no more available UIDs)\n"),
|
|
||||||
log_get_progname());
|
|
||||||
SYSLOG ((LOG_WARN, "no more available UIDs on the system"));
|
|
||||||
free (used_uids);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+38
-23
@@ -1,10 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 1999, Marek Michałkiewicz
|
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
* Copyright (c) 2005 , Tomasz Kłoczko
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
* Copyright (c) 2008 , Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@@ -16,29 +39,23 @@
|
|||||||
#ident "$Id$"
|
#ident "$Id$"
|
||||||
|
|
||||||
|
|
||||||
/*@null@*/char *fgetsx (/*@returned@*/ /*@out@*/char *buf, int cnt, FILE * f)
|
char *fgetsx (char *buf, int cnt, FILE * f)
|
||||||
{
|
{
|
||||||
char *cp = buf;
|
char *cp = buf;
|
||||||
char *ep;
|
char *ep;
|
||||||
|
|
||||||
while (cnt > 0) {
|
while (cnt > 0) {
|
||||||
if (fgets (cp, cnt, f) != cp) {
|
if (fgets (cp, cnt, f) == 0) {
|
||||||
if (cp == buf) {
|
if (cp == buf)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
else
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ep = strrchr (cp, '\\');
|
if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') {
|
||||||
if ((NULL != ep) && (*(ep + 1) == '\n')) {
|
if ((cnt -= ep - cp) > 0)
|
||||||
cnt -= ep - cp;
|
*(cp = ep) = '\0';
|
||||||
if (cnt > 0) {
|
} else
|
||||||
cp = ep;
|
|
||||||
*cp = '\0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -47,10 +64,9 @@ int fputsx (const char *s, FILE * stream)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; '\0' != *s; i++, s++) {
|
for (i = 0; *s; i++, s++) {
|
||||||
if (putc (*s, stream) == EOF) {
|
if (putc (*s, stream) == EOF)
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 /* The standard getgr*() can't handle that. --marekm */
|
#if 0 /* The standard getgr*() can't handle that. --marekm */
|
||||||
if (i > (BUFSIZ / 2)) {
|
if (i > (BUFSIZ / 2)) {
|
||||||
@@ -64,4 +80,3 @@ int fputsx (const char *s, FILE * stream)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
/* $OpenBSD: malloc.c,v 1.267 2020/11/23 15:42:11 otto Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
freezero(void *ptr, size_t sz)
|
|
||||||
{
|
|
||||||
/* This is legal. */
|
|
||||||
if (ptr == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
explicit_bzero(ptr, sz);
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2005 Aurelien Jarno
|
|
||||||
* Copyright © 2006 Robert Millan
|
|
||||||
* Copyright © 2008-2011 Guillem Jover <guillem@hadrons.org>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBBSD_FREEZERO_H
|
|
||||||
#define LIBBSD_FREEZERO_H
|
|
||||||
|
|
||||||
void freezero(void *ptr, size_t size);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2009 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
int get_gid (const char *gidstr, gid_t *gid)
|
|
||||||
{
|
|
||||||
long long int val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtoll (gidstr, &endptr, 10);
|
|
||||||
if ( ('\0' == *gidstr)
|
|
||||||
|| ('\0' != *endptr)
|
|
||||||
|| (ERANGE == errno)
|
|
||||||
|| (/*@+longintegral@*/val != (gid_t)val)/*@=longintegral@*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*gid = val;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
-102
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2009 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
int get_pid (const char *pidstr, pid_t *pid)
|
|
||||||
{
|
|
||||||
long long int val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtoll (pidstr, &endptr, 10);
|
|
||||||
if ( ('\0' == *pidstr)
|
|
||||||
|| ('\0' != *endptr)
|
|
||||||
|| (ERANGE == errno)
|
|
||||||
|| (val < 1)
|
|
||||||
|| (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pid = val;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If use passed in fd:4 as an argument, then return the
|
|
||||||
* value '4', the fd to use.
|
|
||||||
* On error, return -1.
|
|
||||||
*/
|
|
||||||
int get_pidfd_from_fd(const char *pidfdstr)
|
|
||||||
{
|
|
||||||
long long int val;
|
|
||||||
char *endptr;
|
|
||||||
struct stat st;
|
|
||||||
dev_t proc_st_dev, proc_st_rdev;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtoll (pidfdstr, &endptr, 10);
|
|
||||||
if ( ('\0' == *pidfdstr)
|
|
||||||
|| ('\0' != *endptr)
|
|
||||||
|| (ERANGE == errno)
|
|
||||||
|| (val < 0)
|
|
||||||
|| (/*@+longintegral@*/val != (int)val)/*@=longintegral@*/) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat("/proc/self/uid_map", &st) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
proc_st_dev = st.st_dev;
|
|
||||||
proc_st_rdev = st.st_rdev;
|
|
||||||
|
|
||||||
if (fstat(val, &st) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st.st_dev != proc_st_dev || st.st_rdev != proc_st_rdev) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)val;
|
|
||||||
}
|
|
||||||
|
|
||||||
int open_pidfd(const char *pidstr)
|
|
||||||
{
|
|
||||||
int proc_dir_fd;
|
|
||||||
int written;
|
|
||||||
char proc_dir_name[32];
|
|
||||||
pid_t target;
|
|
||||||
|
|
||||||
if (get_pid(pidstr, &target) == 0)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
/* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
|
|
||||||
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
|
|
||||||
target);
|
|
||||||
if ((written <= 0) || ((size_t)written >= sizeof(proc_dir_name))) {
|
|
||||||
fprintf(stderr, "snprintf of proc path failed for %u: %s\n",
|
|
||||||
target, strerror(errno));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
|
|
||||||
if (proc_dir_fd < 0) {
|
|
||||||
fprintf(stderr, _("Could not open proc directory for target %u: %s\n"),
|
|
||||||
target, strerror(errno));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return proc_dir_fd;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2009 , Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include "prototypes.h"
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
int get_uid (const char *uidstr, uid_t *uid)
|
|
||||||
{
|
|
||||||
long long int val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtoll (uidstr, &endptr, 10);
|
|
||||||
if ( ('\0' == *uidstr)
|
|
||||||
|| ('\0' != *endptr)
|
|
||||||
|| (ERANGE == errno)
|
|
||||||
|| (/*@+longintegral@*/val != (uid_t)val)/*@=longintegral@*/) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*uid = val;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1997 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GETDATE_H_
|
|
||||||
#define _GETDATE_H_
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include "defines.h"
|
|
||||||
|
|
||||||
time_t get_date (const char *p, /*@null@*/const time_t *now);
|
|
||||||
#endif
|
|
||||||
+115
-340
@@ -1,10 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2002 - 2006, Tomasz Kłoczko
|
* Copyright (c) 2002 - 2006, Tomasz Kłoczko
|
||||||
* SPDX-FileCopyrightText: 2007 - 2008, Nicolas François
|
* Copyright (c) 2007 - 2008, Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@@ -13,64 +36,18 @@
|
|||||||
|
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
#ifdef USE_ECONF
|
|
||||||
#include <libeconf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "getdef.h"
|
#include "getdef.h"
|
||||||
#include "shadowlog_internal.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A configuration item definition.
|
* A configuration item definition.
|
||||||
*/
|
*/
|
||||||
struct itemdef {
|
struct itemdef {
|
||||||
/*@null@*/const char *name; /* name of the item */
|
const char *name; /* name of the item */
|
||||||
/*@null@*/char *value; /* value given, or NULL if no value */
|
char *value; /* value given, or NULL if no value */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PAMDEFS \
|
|
||||||
{"CHFN_AUTH", NULL}, \
|
|
||||||
{"CHSH_AUTH", NULL}, \
|
|
||||||
{"CRACKLIB_DICTPATH", NULL}, \
|
|
||||||
{"ENV_HZ", NULL}, \
|
|
||||||
{"ENVIRON_FILE", NULL}, \
|
|
||||||
{"ENV_TZ", NULL}, \
|
|
||||||
{"FAILLOG_ENAB", NULL}, \
|
|
||||||
{"FTMP_FILE", NULL}, \
|
|
||||||
{"HMAC_CRYPTO_ALGO", NULL}, \
|
|
||||||
{"ISSUE_FILE", NULL}, \
|
|
||||||
{"LASTLOG_ENAB", NULL}, \
|
|
||||||
{"LOGIN_STRING", NULL}, \
|
|
||||||
{"MAIL_CHECK_ENAB", NULL}, \
|
|
||||||
{"MOTD_FILE", NULL}, \
|
|
||||||
{"NOLOGINS_FILE", NULL}, \
|
|
||||||
{"OBSCURE_CHECKS_ENAB", NULL}, \
|
|
||||||
{"PASS_ALWAYS_WARN", NULL}, \
|
|
||||||
{"PASS_CHANGE_TRIES", NULL}, \
|
|
||||||
{"PASS_MAX_LEN", NULL}, \
|
|
||||||
{"PASS_MIN_LEN", NULL}, \
|
|
||||||
{"PORTTIME_CHECKS_ENAB", NULL}, \
|
|
||||||
{"QUOTAS_ENAB", NULL}, \
|
|
||||||
{"SU_WHEEL_ONLY", NULL}, \
|
|
||||||
{"ULIMIT", NULL},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Items used in other tools (util-linux, etc.)
|
|
||||||
*/
|
|
||||||
#define FOREIGNDEFS \
|
|
||||||
{"ALWAYS_SET_PATH", NULL}, \
|
|
||||||
{"ENV_ROOTPATH", NULL}, \
|
|
||||||
{"LOGIN_KEEP_USERNAME", NULL}, \
|
|
||||||
{"LOGIN_PLAIN_PROMPT", NULL}, \
|
|
||||||
{"MOTD_FIRSTONLY", NULL}, \
|
|
||||||
|
|
||||||
|
|
||||||
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
|
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
|
||||||
static struct itemdef def_table[] = {
|
static struct itemdef def_table[] = {
|
||||||
{"CHFN_RESTRICT", NULL},
|
{"CHFN_RESTRICT", NULL},
|
||||||
@@ -86,10 +63,8 @@ static struct itemdef def_table[] = {
|
|||||||
{"FAKE_SHELL", NULL},
|
{"FAKE_SHELL", NULL},
|
||||||
{"GID_MAX", NULL},
|
{"GID_MAX", NULL},
|
||||||
{"GID_MIN", NULL},
|
{"GID_MIN", NULL},
|
||||||
{"HOME_MODE", NULL},
|
|
||||||
{"HUSHLOGIN_FILE", NULL},
|
{"HUSHLOGIN_FILE", NULL},
|
||||||
{"KILLCHAR", NULL},
|
{"KILLCHAR", NULL},
|
||||||
{"LASTLOG_UID_MAX", NULL},
|
|
||||||
{"LOGIN_RETRIES", NULL},
|
{"LOGIN_RETRIES", NULL},
|
||||||
{"LOGIN_TIMEOUT", NULL},
|
{"LOGIN_TIMEOUT", NULL},
|
||||||
{"LOG_OK_LOGINS", NULL},
|
{"LOG_OK_LOGINS", NULL},
|
||||||
@@ -98,7 +73,6 @@ static struct itemdef def_table[] = {
|
|||||||
{"MAIL_FILE", NULL},
|
{"MAIL_FILE", NULL},
|
||||||
{"MAX_MEMBERS_PER_GROUP", NULL},
|
{"MAX_MEMBERS_PER_GROUP", NULL},
|
||||||
{"MD5_CRYPT_ENAB", NULL},
|
{"MD5_CRYPT_ENAB", NULL},
|
||||||
{"NONEXISTENT", NULL},
|
|
||||||
{"PASS_MAX_DAYS", NULL},
|
{"PASS_MAX_DAYS", NULL},
|
||||||
{"PASS_MIN_DAYS", NULL},
|
{"PASS_MIN_DAYS", NULL},
|
||||||
{"PASS_WARN_AGE", NULL},
|
{"PASS_WARN_AGE", NULL},
|
||||||
@@ -106,19 +80,6 @@ static struct itemdef def_table[] = {
|
|||||||
{"SHA_CRYPT_MAX_ROUNDS", NULL},
|
{"SHA_CRYPT_MAX_ROUNDS", NULL},
|
||||||
{"SHA_CRYPT_MIN_ROUNDS", NULL},
|
{"SHA_CRYPT_MIN_ROUNDS", NULL},
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BCRYPT
|
|
||||||
{"BCRYPT_MAX_ROUNDS", NULL},
|
|
||||||
{"BCRYPT_MIN_ROUNDS", NULL},
|
|
||||||
#endif
|
|
||||||
#ifdef USE_YESCRYPT
|
|
||||||
{"YESCRYPT_COST_FACTOR", NULL},
|
|
||||||
#endif
|
|
||||||
{"SUB_GID_COUNT", NULL},
|
|
||||||
{"SUB_GID_MAX", NULL},
|
|
||||||
{"SUB_GID_MIN", NULL},
|
|
||||||
{"SUB_UID_COUNT", NULL},
|
|
||||||
{"SUB_UID_MAX", NULL},
|
|
||||||
{"SUB_UID_MIN", NULL},
|
|
||||||
{"SULOG_FILE", NULL},
|
{"SULOG_FILE", NULL},
|
||||||
{"SU_NAME", NULL},
|
{"SU_NAME", NULL},
|
||||||
{"SYS_GID_MAX", NULL},
|
{"SYS_GID_MAX", NULL},
|
||||||
@@ -134,48 +95,46 @@ static struct itemdef def_table[] = {
|
|||||||
{"USERDEL_CMD", NULL},
|
{"USERDEL_CMD", NULL},
|
||||||
{"USERGROUPS_ENAB", NULL},
|
{"USERGROUPS_ENAB", NULL},
|
||||||
#ifndef USE_PAM
|
#ifndef USE_PAM
|
||||||
PAMDEFS
|
{"CHFN_AUTH", NULL},
|
||||||
|
{"CHSH_AUTH", NULL},
|
||||||
|
{"CRACKLIB_DICTPATH", NULL},
|
||||||
|
{"ENV_HZ", NULL},
|
||||||
|
{"ENVIRON_FILE", NULL},
|
||||||
|
{"ENV_TZ", NULL},
|
||||||
|
{"FAILLOG_ENAB", NULL},
|
||||||
|
{"FTMP_FILE", NULL},
|
||||||
|
{"ISSUE_FILE", NULL},
|
||||||
|
{"LASTLOG_ENAB", NULL},
|
||||||
|
{"LOGIN_STRING", NULL},
|
||||||
|
{"MAIL_CHECK_ENAB", NULL},
|
||||||
|
{"MOTD_FILE", NULL},
|
||||||
|
{"NOLOGINS_FILE", NULL},
|
||||||
|
{"OBSCURE_CHECKS_ENAB", NULL},
|
||||||
|
{"PASS_ALWAYS_WARN", NULL},
|
||||||
|
{"PASS_CHANGE_TRIES", NULL},
|
||||||
|
{"PASS_MAX_LEN", NULL},
|
||||||
|
{"PASS_MIN_LEN", NULL},
|
||||||
|
{"PORTTIME_CHECKS_ENAB", NULL},
|
||||||
|
{"QUOTAS_ENAB", NULL},
|
||||||
|
{"SU_WHEEL_ONLY", NULL},
|
||||||
|
{"ULIMIT", NULL},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_SYSLOG
|
||||||
{"SYSLOG_SG_ENAB", NULL},
|
{"SYSLOG_SG_ENAB", NULL},
|
||||||
{"SYSLOG_SU_ENAB", NULL},
|
{"SYSLOG_SU_ENAB", NULL},
|
||||||
#ifdef WITH_TCB
|
|
||||||
{"TCB_AUTH_GROUP", NULL},
|
|
||||||
{"TCB_SYMLINKS", NULL},
|
|
||||||
{"USE_TCB", NULL},
|
|
||||||
#endif
|
#endif
|
||||||
{"FORCE_SHADOW", NULL},
|
|
||||||
{"GRANT_AUX_GROUP_SUBIDS", NULL},
|
|
||||||
{"PREVENT_NO_AUTH", NULL},
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
|
|
||||||
static struct itemdef knowndef_table[] = {
|
|
||||||
#ifdef USE_PAM
|
|
||||||
PAMDEFS
|
|
||||||
#endif
|
|
||||||
FOREIGNDEFS
|
|
||||||
{NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef USE_ECONF
|
|
||||||
#ifdef VENDORDIR
|
|
||||||
static const char* vendordir = VENDORDIR;
|
|
||||||
#else
|
|
||||||
static const char* vendordir = NULL;
|
|
||||||
#endif
|
|
||||||
static const char* sysconfdir = "/etc";
|
|
||||||
#else
|
|
||||||
#ifndef LOGINDEFS
|
#ifndef LOGINDEFS
|
||||||
#define LOGINDEFS "/etc/login.defs"
|
#define LOGINDEFS "/etc/login.defs"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* def_fname = LOGINDEFS; /* login config defs file */
|
static char def_fname[] = LOGINDEFS; /* login config defs file */
|
||||||
#endif
|
static int def_loaded = 0; /* are defs already loaded? */
|
||||||
static bool def_loaded = false; /* are defs already loaded? */
|
|
||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *);
|
static struct itemdef *def_find (const char *);
|
||||||
static void def_load (void);
|
static void def_load (void);
|
||||||
|
|
||||||
|
|
||||||
@@ -186,16 +145,14 @@ static void def_load (void);
|
|||||||
* defined. First time invoked, will load definitions from the file.
|
* defined. First time invoked, will load definitions from the file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*@observer@*/ /*@null@*/const char *getdef_str (const char *item)
|
char *getdef_str (const char *item)
|
||||||
{
|
{
|
||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
return ((d = def_find (item)) == NULL ? (char *) NULL : d->value);
|
||||||
return (NULL == d) ? NULL : d->value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -205,18 +162,15 @@ static void def_load (void);
|
|||||||
* Return TRUE if specified item is defined as "yes", else FALSE.
|
* Return TRUE if specified item is defined as "yes", else FALSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool getdef_bool (const char *item)
|
int getdef_bool (const char *item)
|
||||||
{
|
{
|
||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
if ((d = def_find (item)) == NULL || d->value == NULL)
|
||||||
if ((NULL == d) || (NULL == d->value)) {
|
return 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (strcasecmp (d->value, "yes") == 0);
|
return (strcasecmp (d->value, "yes") == 0);
|
||||||
}
|
}
|
||||||
@@ -233,27 +187,14 @@ bool getdef_bool (const char *item)
|
|||||||
int getdef_num (const char *item, int dflt)
|
int getdef_num (const char *item, int dflt)
|
||||||
{
|
{
|
||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
long val;
|
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
if ((d = def_find (item)) == NULL || d->value == NULL)
|
||||||
if ((NULL == d) || (NULL == d->value)) {
|
|
||||||
return dflt;
|
return dflt;
|
||||||
}
|
|
||||||
|
|
||||||
if ( (getlong (d->value, &val) == 0)
|
return (int) strtol (d->value, (char **) NULL, 0);
|
||||||
|| (val > INT_MAX)
|
|
||||||
|| (val < INT_MIN)) {
|
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("configuration error - cannot parse %s value: '%s'"),
|
|
||||||
item, d->value);
|
|
||||||
return dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -268,27 +209,14 @@ int getdef_num (const char *item, int dflt)
|
|||||||
unsigned int getdef_unum (const char *item, unsigned int dflt)
|
unsigned int getdef_unum (const char *item, unsigned int dflt)
|
||||||
{
|
{
|
||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
long val;
|
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
if ((d = def_find (item)) == NULL || d->value == NULL)
|
||||||
if ((NULL == d) || (NULL == d->value)) {
|
|
||||||
return dflt;
|
return dflt;
|
||||||
}
|
|
||||||
|
|
||||||
if ( (getlong (d->value, &val) == 0)
|
return (unsigned int) strtoul (d->value, (char **) NULL, 0);
|
||||||
|| (val < 0)
|
|
||||||
|| (val > INT_MAX)) {
|
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("configuration error - cannot parse %s value: '%s'"),
|
|
||||||
item, d->value);
|
|
||||||
return dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -303,58 +231,16 @@ unsigned int getdef_unum (const char *item, unsigned int dflt)
|
|||||||
long getdef_long (const char *item, long dflt)
|
long getdef_long (const char *item, long dflt)
|
||||||
{
|
{
|
||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
long val;
|
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
if ((d = def_find (item)) == NULL || d->value == NULL)
|
||||||
if ((NULL == d) || (NULL == d->value)) {
|
|
||||||
return dflt;
|
return dflt;
|
||||||
}
|
|
||||||
|
|
||||||
if (getlong (d->value, &val) == 0) {
|
return strtol (d->value, (char **) NULL, 0);
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("configuration error - cannot parse %s value: '%s'"),
|
|
||||||
item, d->value);
|
|
||||||
return dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* getdef_ulong - get unsigned long numerical value from table of definitions
|
|
||||||
*
|
|
||||||
* Returns numeric value of specified item, else the "dflt" value if
|
|
||||||
* the item is not defined. Octal (leading "0") and hex (leading "0x")
|
|
||||||
* values are handled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned long getdef_ulong (const char *item, unsigned long dflt)
|
|
||||||
{
|
|
||||||
struct itemdef *d;
|
|
||||||
unsigned long val;
|
|
||||||
|
|
||||||
if (!def_loaded) {
|
|
||||||
def_load ();
|
|
||||||
}
|
|
||||||
|
|
||||||
d = def_find (item);
|
|
||||||
if ((NULL == d) || (NULL == d->value)) {
|
|
||||||
return dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getulong (d->value, &val) == 0) {
|
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("configuration error - cannot parse %s value: '%s'"),
|
|
||||||
item, d->value);
|
|
||||||
return dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* putdef_str - override the value read from /etc/login.defs
|
* putdef_str - override the value read from /etc/login.defs
|
||||||
@@ -366,31 +252,29 @@ int putdef_str (const char *name, const char *value)
|
|||||||
struct itemdef *d;
|
struct itemdef *d;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
if (!def_loaded) {
|
if (!def_loaded)
|
||||||
def_load ();
|
def_load ();
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate the slot to save the value. If this parameter
|
* Locate the slot to save the value. If this parameter
|
||||||
* is unknown then "def_find" will print an err message.
|
* is unknown then "def_find" will print an err message.
|
||||||
*/
|
*/
|
||||||
d = def_find (name);
|
if ((d = def_find (name)) == NULL)
|
||||||
if (NULL == d) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save off the value.
|
* Save off the value.
|
||||||
*/
|
*/
|
||||||
cp = strdup (value);
|
if ((cp = strdup (value)) == NULL) {
|
||||||
if (NULL == cp) {
|
fputs (_("Could not allocate space for config info.\n"),
|
||||||
(void) fputs (_("Could not allocate space for config info.\n"),
|
stderr);
|
||||||
shadow_logfd);
|
|
||||||
SYSLOG ((LOG_ERR, "could not allocate space for config info"));
|
SYSLOG ((LOG_ERR, "could not allocate space for config info"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (d->value);
|
if (d->value)
|
||||||
|
free (d->value);
|
||||||
|
|
||||||
d->value = cp;
|
d->value = cp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -403,67 +287,31 @@ int putdef_str (const char *name, const char *value)
|
|||||||
* specified configuration option.
|
* specified configuration option.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
|
static struct itemdef *def_find (const char *name)
|
||||||
{
|
{
|
||||||
|
int n;
|
||||||
struct itemdef *ptr;
|
struct itemdef *ptr;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search into the table.
|
* Search into the table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (ptr = def_table; NULL != ptr->name; ptr++) {
|
for (ptr = def_table; ptr->name; ptr++) {
|
||||||
if (strcmp (ptr->name, name) == 0) {
|
if (!(n = strcmp (ptr->name, name)))
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Item was never found.
|
* Item was never found.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
|
fprintf (stderr,
|
||||||
if (strcmp (ptr->name, name) == 0) {
|
_
|
||||||
goto out;
|
("configuration error - unknown item '%s' (notify administrator)\n"),
|
||||||
}
|
name);
|
||||||
}
|
|
||||||
fprintf (shadow_logfd,
|
|
||||||
_("configuration error - unknown item '%s' (notify administrator)\n"),
|
|
||||||
name);
|
|
||||||
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
|
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
|
||||||
|
return (struct itemdef *) NULL;
|
||||||
out:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* setdef_config_file - set the default configuration file path
|
|
||||||
*
|
|
||||||
* must be called prior to any def* calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setdef_config_file (const char* file)
|
|
||||||
{
|
|
||||||
#ifdef USE_ECONF
|
|
||||||
size_t len;
|
|
||||||
char* cp;
|
|
||||||
|
|
||||||
len = strlen(file) + strlen(sysconfdir) + 2;
|
|
||||||
cp = MALLOC(len, char);
|
|
||||||
if (cp == NULL)
|
|
||||||
exit (13);
|
|
||||||
snprintf(cp, len, "%s/%s", file, sysconfdir);
|
|
||||||
sysconfdir = cp;
|
|
||||||
#ifdef VENDORDIR
|
|
||||||
len = strlen(file) + strlen(vendordir) + 2;
|
|
||||||
cp = MALLOC(len, char);
|
|
||||||
if (cp == NULL)
|
|
||||||
exit (13);
|
|
||||||
snprintf(cp, len, "%s/%s", file, vendordir);
|
|
||||||
vendordir = cp;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
def_fname = file;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -472,87 +320,26 @@ void setdef_config_file (const char* file)
|
|||||||
* Loads the user-configured options from the default configuration file
|
* Loads the user-configured options from the default configuration file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_ECONF
|
|
||||||
static void def_load (void)
|
|
||||||
{
|
|
||||||
econf_file *defs_file = NULL;
|
|
||||||
econf_err error;
|
|
||||||
char **keys;
|
|
||||||
size_t key_number;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the initialized flag.
|
|
||||||
* (do it early to prevent recursion in putdef_str())
|
|
||||||
*/
|
|
||||||
def_loaded = true;
|
|
||||||
|
|
||||||
error = econf_readDirs (&defs_file, vendordir, sysconfdir, "login", "defs", " \t", "#");
|
|
||||||
if (error) {
|
|
||||||
if (error == ECONF_NOFILE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SYSLOG ((LOG_CRIT, "cannot open login definitions [%s]",
|
|
||||||
econf_errString(error)));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((error = econf_getKeys(defs_file, NULL, &key_number, &keys))) {
|
|
||||||
SYSLOG ((LOG_CRIT, "cannot read login definitions [%s]",
|
|
||||||
econf_errString(error)));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < key_number; i++) {
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
error = econf_getStringValue(defs_file, NULL, keys[i], &value);
|
|
||||||
if (error) {
|
|
||||||
SYSLOG ((LOG_CRIT, "failed reading key %zu from econf [%s]",
|
|
||||||
i, econf_errString(error)));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Store the value in def_table.
|
|
||||||
*
|
|
||||||
* Ignore failures to load the login.defs file.
|
|
||||||
* The error was already reported to the user and to
|
|
||||||
* syslog. The tools will just use their default values.
|
|
||||||
*/
|
|
||||||
(void)putdef_str (keys[i], value);
|
|
||||||
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
econf_free (keys);
|
|
||||||
econf_free (defs_file);
|
|
||||||
}
|
|
||||||
#else /* USE_ECONF */
|
|
||||||
static void def_load (void)
|
static void def_load (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[1024], *name, *value, *s;
|
char buf[1024], *name, *value, *s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the configuration definitions file.
|
||||||
|
*/
|
||||||
|
if ((fp = fopen (def_fname, "r")) == NULL) {
|
||||||
|
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%m]",
|
||||||
|
def_fname));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the initialized flag.
|
* Set the initialized flag.
|
||||||
* (do it early to prevent recursion in putdef_str())
|
* (do it early to prevent recursion in putdef_str())
|
||||||
*/
|
*/
|
||||||
def_loaded = true;
|
++def_loaded;
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the configuration definitions file.
|
|
||||||
*/
|
|
||||||
fp = fopen (def_fname, "r");
|
|
||||||
if (NULL == fp) {
|
|
||||||
if (errno == ENOENT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int err = errno;
|
|
||||||
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
|
|
||||||
def_fname, strerror (err)));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Go through all of the lines in the file.
|
* Go through all of the lines in the file.
|
||||||
@@ -562,13 +349,11 @@ static void def_load (void)
|
|||||||
/*
|
/*
|
||||||
* Trim trailing whitespace.
|
* Trim trailing whitespace.
|
||||||
*/
|
*/
|
||||||
for (i = (ptrdiff_t) strlen (buf) - 1; i >= 0; --i) {
|
for (i = strlen (buf) - 1; i >= 0; --i) {
|
||||||
if (!isspace (buf[i])) {
|
if (!isspace (buf[i]))
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
buf[++i] = '\0';
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Break the line into two fields.
|
* Break the line into two fields.
|
||||||
@@ -587,24 +372,18 @@ static void def_load (void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the value in def_table.
|
* Store the value in def_table.
|
||||||
*
|
|
||||||
* Ignore failures to load the login.defs file.
|
|
||||||
* The error was already reported to the user and to
|
|
||||||
* syslog. The tools will just use their default values.
|
|
||||||
*/
|
*/
|
||||||
(void)putdef_str (name, value);
|
putdef_str (name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ferror (fp) != 0) {
|
if (ferror (fp)) {
|
||||||
int err = errno;
|
SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%m]",
|
||||||
SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%s]",
|
def_fname));
|
||||||
def_fname, strerror (err)));
|
exit (1);
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) fclose (fp);
|
(void) fclose (fp);
|
||||||
}
|
}
|
||||||
#endif /* USE_ECONF */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CKDEFS
|
#ifdef CKDEFS
|
||||||
@@ -617,22 +396,18 @@ int main (int argc, char **argv)
|
|||||||
def_load ();
|
def_load ();
|
||||||
|
|
||||||
for (i = 0; i < NUMDEFS; ++i) {
|
for (i = 0; i < NUMDEFS; ++i) {
|
||||||
d = def_find (def_table[i].name);
|
if ((d = def_find (def_table[i].name)) == NULL)
|
||||||
if (NULL == d) {
|
|
||||||
printf ("error - lookup '%s' failed\n",
|
printf ("error - lookup '%s' failed\n",
|
||||||
def_table[i].name);
|
def_table[i].name);
|
||||||
} else {
|
else
|
||||||
printf ("%4d %-24s %s\n", i + 1, d->name, d->value);
|
printf ("%4d %-24s %s\n", i + 1, d->name, d->value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
cp = getdef_str (argv[1]);
|
if ((cp = getdef_str (argv[1])) != NULL)
|
||||||
if (NULL != cp) {
|
|
||||||
printf ("%s `%s'\n", argv[1], cp);
|
printf ("%s `%s'\n", argv[1], cp);
|
||||||
} else {
|
else
|
||||||
printf ("%s not found\n", argv[1]);
|
printf ("%s not found\n", argv[1]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exit (EXIT_SUCCESS);
|
exit (0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+29
-9
@@ -1,23 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
||||||
* SPDX-FileCopyrightText: 2002 - 2006, Tomasz Kłoczko
|
* Copyright (c) 2002 - 2006, Tomasz Kłoczko
|
||||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#ifndef _GETDEF_H
|
#ifndef _GETDEF_H
|
||||||
#define _GETDEF_H
|
#define _GETDEF_H
|
||||||
|
|
||||||
/* getdef.c */
|
/* getdef.c */
|
||||||
extern bool getdef_bool (const char *);
|
extern int getdef_bool (const char *);
|
||||||
extern long getdef_long (const char *, long);
|
extern long getdef_long (const char *, long);
|
||||||
extern int getdef_num (const char *, int);
|
extern int getdef_num (const char *, int);
|
||||||
extern unsigned long getdef_ulong (const char *, unsigned long);
|
|
||||||
extern unsigned int getdef_unum (const char *, unsigned int);
|
extern unsigned int getdef_unum (const char *, unsigned int);
|
||||||
extern /*@observer@*/ /*@null@*/const char *getdef_str (const char *);
|
extern char *getdef_str (const char *);
|
||||||
extern int putdef_str (const char *, const char *);
|
extern int putdef_str (const char *, const char *);
|
||||||
extern void setdef_config_file (const char* file);
|
|
||||||
|
|
||||||
/* default UMASK value if not specified in /etc/login.defs */
|
/* default UMASK value if not specified in /etc/login.defs */
|
||||||
#define GETDEF_DEFAULT_UMASK 022
|
#define GETDEF_DEFAULT_UMASK 022
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
|
|
||||||
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
||||||
* SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getgr_nam_gid - Return a pointer to the group specified by a string.
|
|
||||||
* The string may be a valid GID or a valid groupname.
|
|
||||||
* If the group does not exist on the system, NULL is returned.
|
|
||||||
*/
|
|
||||||
extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname)
|
|
||||||
{
|
|
||||||
long long int gid;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
if (NULL == grname) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
gid = strtoll (grname, &endptr, 10);
|
|
||||||
if ( ('\0' != *grname)
|
|
||||||
&& ('\0' == *endptr)
|
|
||||||
&& (ERANGE != errno)
|
|
||||||
&& (/*@+longintegral@*/gid == (gid_t)gid)/*@=longintegral@*/) {
|
|
||||||
return xgetgrgid (gid);
|
|
||||||
}
|
|
||||||
return xgetgrnam (grname);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ident "$Id$"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "prototypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getlong - extract a long integer provided by the numstr string in *result
|
|
||||||
*
|
|
||||||
* It supports decimal, hexadecimal or octal representations.
|
|
||||||
*
|
|
||||||
* Returns 0 on failure, 1 on success.
|
|
||||||
*/
|
|
||||||
int getlong (const char *numstr, /*@out@*/long int *result)
|
|
||||||
{
|
|
||||||
long val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtol (numstr, &endptr, 0);
|
|
||||||
if (('\0' == *numstr) || ('\0' != *endptr) || (ERANGE == errno)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*result = val;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user