2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

Merge sudo 1.9.12 from tip.

--HG--
branch : 1.9
This commit is contained in:
Todd C. Miller 2022-10-21 17:04:21 -06:00
commit c684bf0830
336 changed files with 29415 additions and 20628 deletions

View File

@ -13,12 +13,12 @@ name: "CodeQL"
on:
push:
branches: [ main ]
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
branches: [ "main" ]
schedule:
- cron: '19 3 * * 2'
- cron: '25 15 * * 0'
jobs:
analyze:
@ -34,37 +34,39 @@ jobs:
matrix:
language: [ 'cpp', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
#- run: |
# make bootstrap
# make release
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

View File

@ -30,13 +30,13 @@ for a list of packages required to build sudo.
## Simple sudo installation
0. If you are upgrading from a previous version of sudo, read
1. If you are upgrading from a previous version of sudo, read
[docs/UPGRADE.md](docs/UPGRADE.md) before proceeding.
1. Read the "OS dependent notes" section for any particular
2. Read the "OS dependent notes" section for any particular
"gotchas" relating to your operating system.
2. `cd` to the source or build directory and type `./configure`
3. `cd` to the source or build directory and type `./configure`
to generate a Makefile and config.h file suitable for building
sudo. Before you actually run configure you should read the
"Available configure options" section to see if there are
@ -320,7 +320,7 @@ Defaults are listed in brackets after the description.
Adds the specified library (or libraries) to SUDO_LIBS and
and VISUDO_LIBS so sudo will link against them. If the
library doesn't start with "-l" or end in ".a" or ".o" a
"-l" will be pre-pended to it. Multiple libraries may be
"-l" will be prepended to it. Multiple libraries may be
specified as long as they are space separated.
--with-libtool=PATH

View File

@ -296,7 +296,7 @@ The file getentropy.c bears the following license:
The embedded copy of zlib bears the following license:
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -319,7 +319,7 @@ The embedded copy of zlib bears the following license:
The embedded copy of protobuf-c bears the following license:
Copyright (c) 2008-2018, Dave Benson and the protobuf-c authors.
Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -220,6 +220,7 @@ lib/util/event_select.c
lib/util/explicit_bzero.c
lib/util/fatal.c
lib/util/fchmodat.c
lib/util/fchownat.c
lib/util/fnmatch.c
lib/util/freezero.c
lib/util/fstatat.c
@ -251,6 +252,8 @@ lib/util/mkdirat.c
lib/util/mksiglist.c
lib/util/mksigname.c
lib/util/mktemp.c
lib/util/mmap_alloc.c
lib/util/multiarch.c
lib/util/nanosleep.c
lib/util/openat.c
lib/util/parseln.c
@ -278,6 +281,8 @@ lib/util/regress/glob/globtest.c
lib/util/regress/glob/globtest.in
lib/util/regress/harness.in
lib/util/regress/mktemp/mktemp_test.c
lib/util/regress/multiarch/multiarch_test.c
lib/util/regress/open_parent_dir/open_parent_dir_test.c
lib/util/regress/parse_gids/parse_gids_test.c
lib/util/regress/progname/progname_test.c
lib/util/regress/strsig/strsig_test.c
@ -1018,6 +1023,8 @@ plugins/sudoers/regress/testsudoers/test17.out.ok
plugins/sudoers/regress/testsudoers/test17.sh
plugins/sudoers/regress/testsudoers/test18.out.ok
plugins/sudoers/regress/testsudoers/test18.sh
plugins/sudoers/regress/testsudoers/test19.out.ok
plugins/sudoers/regress/testsudoers/test19.sh
plugins/sudoers/regress/testsudoers/test2.inc
plugins/sudoers/regress/testsudoers/test2.out.ok
plugins/sudoers/regress/testsudoers/test2.sh
@ -1196,6 +1203,7 @@ src/exec.c
src/exec_common.c
src/exec_intercept.c
src/exec_intercept.h
src/exec_iolog.c
src/exec_monitor.c
src/exec_nopty.c
src/exec_preload.c

View File

@ -58,10 +58,10 @@ python_version = @PYTHON_VERSION@
SUBDIRS = lib/util @ZLIB_SRC@ lib/eventlog lib/fuzzstub lib/iolog \
lib/protobuf-c @LOGSRV_SRC@ @LOGSRVD_SRC@ plugins/audit_json \
plugins/group_file plugins/sample_approval plugins/sudoers \
plugins/system_group @PYTHON_PLUGIN_SRC@ src include docs examples
plugins/group_file plugins/sudoers plugins/system_group \
@PYTHON_PLUGIN_SRC@ src include docs examples
SAMPLES = plugins/sample
SAMPLES = plugins/sample plugins/sample_approval
VERSION = @PACKAGE_VERSION@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
@ -70,6 +70,8 @@ LIBTOOL_DEPS = @LIBTOOL_DEPS@
SHELL = @SHELL@
EGREP = @EGREP@
GREP = @GREP@
SED = @SED@
INSTALL = $(SHELL) $(scriptdir)/install-sh -c
@ -105,19 +107,19 @@ PVS_IGNORE = 'V707,V011,V002,V536,V568'
PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
all: config.status
for d in $(SUBDIRS); do \
for d in $(SUBDIRS) $(SAMPLES); do \
(cd $$d && exec $(MAKE) $@) && continue; \
exit $$?; \
done
check check-verbose check-fuzzer fuzz pre-install: config.status
for d in $(SUBDIRS); do \
for d in $(SUBDIRS) $(SAMPLES); do \
(cd $$d && exec $(MAKE) $@) && continue; \
exit $$?; \
done
uncrustify.files: Makefile
grep '\.[ch]$$' $(top_srcdir)/MANIFEST | egrep -v '(/zlib/|/(arc4random|arc4random_uniform|chacha_private|charclass|fnmatch|getaddrinfo|getcwd|getdate|getentropy|getopt|getopt_long|glob|gram|inet_ntop|inet_pton|log_server.pb-c|mktemp|pw_dup|reallocarray|mktemp_test|protobuf-c|snprintf|stdbool|strlcat|strlcpy|sudo_queue|toke)\.[ch]$$)' > uncrustify.files
$(GREP) '\.[ch]$$' $(top_srcdir)/MANIFEST | $(EGREP) -v '(/zlib/|/(arc4random|arc4random_uniform|chacha_private|charclass|fnmatch|getaddrinfo|getcwd|getdate|getentropy|getopt|getopt_long|glob|gram|inet_ntop|inet_pton|log_server.pb-c|mktemp|pw_dup|reallocarray|mktemp_test|protobuf-c|snprintf|stdbool|strlcat|strlcpy|sudo_queue|toke)\.[ch]$$)' > uncrustify.files
reformat: uncrustify.files
( cd $(top_srcdir) && uncrustify -c etc/uncrustify.cfg --replace --no-backup -F $(top_builddir)/uncrustify.files )
@ -126,11 +128,11 @@ check-format: uncrustify.files
( cd $(top_srcdir) && uncrustify -c etc/uncrustify.cfg --check -F $(top_builddir)/uncrustify.files )
spell:
( cd $(top_srcdir) && codespell -I etc/codespell.ignore -x etc/codespell.exclude `egrep -v -f etc/codespell.skip MANIFEST` )
( cd $(top_srcdir) && codespell -I etc/codespell.ignore -x etc/codespell.exclude `$(EGREP) -v -f etc/codespell.skip MANIFEST` )
cppcheck: config.status
rval=0; \
for d in $(SUBDIRS); do \
for d in $(SUBDIRS) $(SAMPLES); do \
echo checking $$d; \
(cd $$d && exec $(MAKE) CPPCHECK_OPTS="$(CPPCHECK_OPTS)" $@) || rval=`expr $$rval + $$?`; \
done; \
@ -138,7 +140,7 @@ cppcheck: config.status
splint: config.status
rval=0; \
for d in $(SUBDIRS); do \
for d in $(SUBDIRS) $(SAMPLES); do \
echo splinting $$d; \
(cd $$d && exec $(MAKE) SPLINT_OPTS="$(SPLINT_OPTS)" $@) || rval=`expr $$rval + $$?`; \
done; \
@ -161,7 +163,7 @@ cov-analyze: cov-upload
pvs-studio: config.status
files=; \
rval=0; \
for d in $(SUBDIRS); do \
for d in $(SUBDIRS) $(SAMPLES); do \
(cd $$d && exec $(MAKE) PVS_IGNORE="$(PVS_IGNORE)" pvs-log-files) || rval=`expr $$rval + $$?`; \
for f in $$d/*.plog; do \
if test "$$f" != "$$d/*.plog"; then \
@ -234,7 +236,7 @@ depend: siglist.c signame.c
ChangeLog:
if test -d $(srcdir)/.hg; then \
if hg log -R $(srcdir) --style=changelog -r "sort(branch(.) or follow(), -date)" > $@.tmp; then \
if hg log -R $(srcdir) --template=changelog -r "sort(branch(.) or follow(), -date)" > $@.tmp; then \
mv -f $@.tmp $(srcdir)/$@; \
else \
rm -f $@.tmp; \
@ -440,4 +442,4 @@ sandwich:
fi
.PHONY: clean mostlyclean distclean cleandir clobber realclean ChangeLog \
me a sandwhich check-format reformat
me a sandwich check-format reformat

124
NEWS
View File

@ -1,3 +1,127 @@
What's new in Sudo 1.9.12
* Fixed a bug in the ptrace-based intercept mode where the current
working directory could include garbage at the end.
* Fixed a compilation error on systems that lack the stdint.h
header. Bug #1035
* Fixed a bug when logging the command's exit status in intercept
mode. The wrong command could be logged with the exit status.
* For ptrace-based intercept mode, sudo will now attempt to
verify that the command path name, arguments and environment
have not changed from the time when they were authorized by the
security policy. The new "intercept_verify" sudoers setting can
be used to control this behavior.
* Fixed running commands with a relative path (e.g. ./foo) in
intercept mode. Previously, this would fail if sudo's current
working directory was different from that of the command.
* Sudo now supports passing the execve(2) system call the NULL
pointer for the `argv` and/or `envp` arguments when in intercept
mode. Linux treats a NULL pointer like an empty array.
* The sudoers LDAP schema now allows sudoUser, sudoRunasUser and
sudoRunasGroup to include UTF-8 characters, not just 7-bit ASCII.
* Fixed a problem with "sudo -i" on SELinux when the target user's
home directory is not searchable by sudo. GitHub issue #160.
* Neovim has been added to the list of visudo editors that support
passing the line number on the command line.
* Fixed a bug in sudo's SHA384 and SHA512 message digest padding.
* Added a new "-N" (--no-update) command line option to sudo which
can be used to prevent sudo from updating the user's cached
credentials. It is now possible to determine whether or not a
user's cached credentials are currently valid by running:
$ sudo -Nnv
and checking the exit value. One use case for this is to indicate
in a shell prompt that sudo is "active" for the user.
* PAM approval modules are no longer invoked when running sub-commands
in intercept mode unless the "intercept_authenticate" option is set.
There is a substantial performance penalty for calling into PAM
for each command run. PAM approval modules are still called for
the initial command.
* Intercept mode on Linux now uses process_vm_readv(2) and
process_vm_writev(2) if available.
* The XDG_CURRENT_DESKTOP environment variable is now preserved
by default. This makes it possible for graphical applications
to choose the correct theme when run via sudo.
* On 64-bit systems, if sudo fails to load a sudoers group plugin,
it will use system-specific heuristics to try to locate a 64-bit
version of the plugin.
* The cvtsudoers manual now documents the JSON and CSV output
formats. GitHub issue #172.
* Fixed a bug where sub-commands were not being logged to a remote
log server when log_subcmds was enabled. GitHub issue #174.
* The new log_stdin, log_stdout, log_stderr, log_ttyin, and log_ttyout
sudoers settings can be used to support more fine-grained I/O logging.
The sudo front-end no longer allocates a pseudo-terminal when running
a command if the I/O logging plugin requests logging of stdin, stdout,
or stderr but not terminal input/output.
* Quieted a libgcrypt run-time initialization warning.
This fixes Debian bug #1019428 and Ubuntu bug #1397663.
* Fixed a bug in visudo that caused literal backslashes to be removed
from the EDITOR environment variable. GitHub issue #179.
* The sudo Python plugin now implements the "find_spec" method instead
of the the deprecated "find_module". This fixes a test failure when
a newer version of setuptools that doesn't include "find_module" is
found on the system.
* Fixed a bug introduced in sudo 1.9.9 where sudo_logsrvd created
the process ID file, usually /var/run/sudo/sudo_logsrvd.pid, as
a directory instead of a plain file. The same bug could result
in I/O log directories that end in six or more X's being created
literally in addition to the name being used as a template for
the mkdtemp(3) function.
* Fixed a long-standing bug where a sudoers rule with a command
line argument of "", which indicates the command may be run with
no arguments, would also match a literal "" on the command line.
GitHub issue #182.
* Added the -I option to visudo which only edits the main sudoers
file. Include files are not edited unless a syntax error is found.
* Fixed "sudo -l -U otheruser" output when the runas list is empty.
Previously, sudo would list the invoking user instead of the
list user. GitHub issue #183.
* Fixed the display of command tags and options in "sudo -l" output
when the RunAs user or group changes. A new line is started for
RunAs changes which means we need to display the command tags
and options again. GitHub issue #184.
* The sesh helper program now uses getopt_long(3) to parse the
command line options.
* The embedded copy of zlib has been updated to version 1.2.13.
* Fixed a bug that prevented event log data from being sent to the
log server when I/O logging was not enabled. This only affected
systems without PAM or configurations where the pam_session and
pam_setcred options were disabled in the sudoers file.
* Fixed a bug where "sudo -l" output included a carriage return
after the newline. This is only needed when displaying to a
terminal in raw mode. Bug #1042.
What's new in Sudo 1.9.11p3
* Fixed "connection reset" errors on AIX when running shell scripts

View File

@ -298,6 +298,9 @@
/* Define to 1 if you have the `fchmodat' function. */
#undef HAVE_FCHMODAT
/* Define to 1 if you have the `fchownat' function. */
#undef HAVE_FCHOWNAT
/* Define to 1 if your system has the F_CLOSEM fcntl. */
#undef HAVE_FCNTL_CLOSEM
@ -599,11 +602,17 @@
/* Define to 1 if you have the `mkdirat' function. */
#undef HAVE_MKDIRAT
/* Define to 1 if you have the `mkdtemp' function. */
#undef HAVE_MKDTEMP
/* Define to 1 if you have the `mkdtempat' function. */
#undef HAVE_MKDTEMPAT
/* Define to 1 if you have the `mkstemps' function. */
#undef HAVE_MKSTEMPS
/* Define to 1 if you have the `mkdtempat_np' function. */
#undef HAVE_MKDTEMPAT_NP
/* Define to 1 if you have the `mkostempsat' function. */
#undef HAVE_MKOSTEMPSAT
/* Define to 1 if you have the `mkostempsat_np' function. */
#undef HAVE_MKOSTEMPSAT_NP
/* Define to 1 if you have the <mps/ldap_ssl.h> header file. */
#undef HAVE_MPS_LDAP_SSL_H
@ -686,6 +695,9 @@
/* Define to 1 if you have the `priv_set' function. */
#undef HAVE_PRIV_SET
/* Define to 1 if you have the `process_vm_readv' function. */
#undef HAVE_PROCESS_VM_READV
/* Define to 1 if you have the <procfs.h> header file. */
#undef HAVE_PROCFS_H
@ -1448,7 +1460,53 @@
code using `volatile' can become incorrect without. Disable with care. */
#undef volatile
/* Symbol visibility controls */
#ifndef __GNUC_PREREQ__
# ifdef __GNUC__
# define __GNUC_PREREQ__(ma, mi) \
((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
# else
# define __GNUC_PREREQ__(ma, mi) 0
# endif
#endif
/* Define away __attribute__ for non-gcc or old gcc. */
#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5)
# define __attribute__(x)
#endif
/* For functions that call exit() directly. */
#if __GNUC_PREREQ__(2, 5)
# define sudo_noreturn __attribute__((__noreturn__))
#else
# define sudo_noreturn
#endif
/* For malloc-like functions that return uninitialized or zeroed memory. */
#if __GNUC_PREREQ__(2, 96)
# define sudo_malloclike __attribute__((__malloc__))
#else
# define sudo_malloclike
#endif
/* Compile-time checking for function arguments that must not be NULL. */
#if __GNUC_PREREQ__(3, 3)
# define sudo_attr_nonnull(_a) __attribute__((__nonnull__ (_a)))
#else
# define sudo_attr_nonnull(_a)
#endif
/* For catching format string mismatches. */
#if __GNUC_PREREQ__(2, 7)
# define sudo_printflike(_f, _v) __attribute__((__format__ (__printf__, _f, _v))) sudo_attr_nonnull(_f)
# define sudo_printf0like(_f, _v) __attribute__((__format__ (__printf__, _f, _v)))
# define sudo_attr_fmt_arg(_f) __attribute__((__format_arg__ (_f)))
#else
# define sudo_printflike(_f, _v)
# define sudo_printf0like(_f, _v)
# define sudo_attr_fmt_arg(_f)
#endif
/* Symbol visibility controls. */
#ifdef HAVE_DSO_VISIBILITY
# if defined(__GNUC__)
# define sudo_dso_public __attribute__((__visibility__("default")))

96
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for sudo 1.9.11p3.
# Generated by GNU Autoconf 2.71 for sudo 1.9.12.
#
# Report bugs to <https://bugzilla.sudo.ws/>.
#
@ -621,8 +621,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sudo'
PACKAGE_TARNAME='sudo'
PACKAGE_VERSION='1.9.11p3'
PACKAGE_STRING='sudo 1.9.11p3'
PACKAGE_VERSION='1.9.12'
PACKAGE_STRING='sudo 1.9.12'
PACKAGE_BUGREPORT='https://bugzilla.sudo.ws/'
PACKAGE_URL=''
@ -1640,7 +1640,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sudo 1.9.11p3 to adapt to many kinds of systems.
\`configure' configures sudo 1.9.12 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1706,7 +1706,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sudo 1.9.11p3:";;
short | recursive ) echo "Configuration of sudo 1.9.12:";;
esac
cat <<\_ACEOF
@ -1996,7 +1996,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sudo configure 1.9.11p3
sudo configure 1.9.12
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@ -2653,7 +2653,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sudo $as_me 1.9.11p3, which was
It was created by sudo $as_me 1.9.12, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@ -17851,9 +17851,23 @@ fi
# We use our own getentropy() by default on Linux.
: ${ac_cv_func_getentropy='no'}
# The glibc arc4random() may fail in chroot on older kernels.
# We use our own arc4random() by default on Linux.
: ${ac_cv_func_arc4random='no'}
# The glibc closefrom() emulation may fail in chroot.
# We use our own closefrom() by default on Linux.
: ${ac_cv_func_closefrom='no'}
# Linux 3.2 supports reading/writing a another process
# without using ptrace(2).
ac_fn_c_check_func "$LINENO" "process_vm_readv" "ac_cv_func_process_vm_readv"
if test "x$ac_cv_func_process_vm_readv" = xyes
then :
printf "%s\n" "#define HAVE_PROCESS_VM_READV 1" >>confdefs.h
fi
;;
*-*-gnu*)
# lockf() is broken on the Hurd
@ -22733,6 +22747,32 @@ esac
fi
fi
done
for ac_func in fchownat
do :
ac_fn_c_check_func "$LINENO" "fchownat" "ac_cv_func_fchownat"
if test "x$ac_cv_func_fchownat" = xyes
then :
printf "%s\n" "#define HAVE_FCHOWNAT 1" >>confdefs.h
else $as_nop
case " $LIBOBJS " in
*" fchownat.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS fchownat.$ac_objext"
;;
esac
for _sym in sudo_fchownat; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
fi
done
@ -23297,8 +23337,12 @@ fi
fi
done
sudo_mktemp=no
case "$host_os" in
darwin*)
# macOS has these but uses a _np (non-portable) suffix
for ac_func in mkstemps mkdtemp
for ac_func in mkdtempat_np mkostempsat_np
do :
as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -23309,11 +23353,32 @@ then :
_ACEOF
else $as_nop
break
sudo_mktemp=yes; break
fi
done
if test X"$ac_cv_func_mkstemps$ac_cv_func_mkdtemp" != X"yesyes"; then
;;
*)
for ac_func in mkdtempat mkostempsat
do :
as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"
then :
cat >>confdefs.h <<_ACEOF
#define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
else $as_nop
sudo_mktemp=yes; break
fi
done
;;
esac
# If any of the mktemp family are missing we use our own.
if test X"$sudo_mktemp" = X"yes"; then
for ac_func in arc4random random lrand48
do :
@ -23343,9 +23408,8 @@ fi
;;
esac
# If either mkdtemp() or mkstemps() is missing, replace both.
for _sym in sudo_mkdtemp sudo_mkstemps; do
for _sym in sudo_mkdtemp sudo_mkdtempat sudo_mkostempsat sudo_mkstemp sudo_mkstemps; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
@ -32298,7 +32362,7 @@ printf "%s\n" "#define os_init $OS_INIT" >>confdefs.h
if test -n "$GCC"; then
if test X"$enable_warnings" = X"yes" -o X"$with_devel" = X"yes"; then
CFLAGS="${CFLAGS} -Wall -Wsign-compare -Wpointer-arith -Wno-unknown-pragmas"
CFLAGS="${CFLAGS} -Wall -Wsign-compare -Wpointer-arith -Wno-unknown-pragmas -Wmissing-prototypes -Wwrite-strings"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshadow" >&5
printf %s "checking whether C compiler accepts -Wshadow... " >&6; }
if test ${ax_cv_check_cflags___Wshadow+y}
@ -32384,7 +32448,7 @@ printf "%s\n" "$sudo_cv_var_fallthrough_attribute" >&6; }
if test X"$enable_werror" = X"yes"; then
CFLAGS="${CFLAGS} -Werror"
fi
case "$host" in
case "$host_os" in
# Avoid unwanted warnings on macOS
darwin*) CFLAGS="${CFLAGS} -Wno-deprecated-declarations";;
esac
@ -33050,7 +33114,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sudo $as_me 1.9.11p3, which was
This file was extended by sudo $as_me 1.9.12, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -33118,7 +33182,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
sudo config.status 1.9.11p3
sudo config.status 1.9.12
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View File

@ -18,7 +18,7 @@ dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
dnl OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
dnl
AC_PREREQ([2.70])
AC_INIT([sudo], [1.9.11p3], [https://bugzilla.sudo.ws/], [sudo])
AC_INIT([sudo], [1.9.12], [https://bugzilla.sudo.ws/], [sudo])
AC_CONFIG_HEADERS([config.h pathnames.h])
AC_CONFIG_SRCDIR([src/sudo.c])
AC_CONFIG_AUX_DIR([scripts])
@ -2080,9 +2080,17 @@ case "$host" in
# We use our own getentropy() by default on Linux.
: ${ac_cv_func_getentropy='no'}
# The glibc arc4random() may fail in chroot on older kernels.
# We use our own arc4random() by default on Linux.
: ${ac_cv_func_arc4random='no'}
# The glibc closefrom() emulation may fail in chroot.
# We use our own closefrom() by default on Linux.
: ${ac_cv_func_closefrom='no'}
# Linux 3.2 supports reading/writing a another process
# without using ptrace(2).
AC_CHECK_FUNCS([process_vm_readv])
;;
*-*-gnu*)
# lockf() is broken on the Hurd
@ -2865,6 +2873,10 @@ AC_CHECK_FUNCS(nanosleep, [], [
SUDO_APPEND_COMPAT_EXP(sudo_nanosleep)
])
])
AC_CHECK_FUNCS([fchownat], [], [
AC_LIBOBJ(fchownat)
SUDO_APPEND_COMPAT_EXP(sudo_fchownat)
])
AC_CHECK_FUNCS([mkdirat], [], [
AC_LIBOBJ(mkdirat)
SUDO_APPEND_COMPAT_EXP(sudo_mkdirat)
@ -2949,15 +2961,24 @@ AC_CHECK_FUNCS([closefrom], [], [AC_LIBOBJ(closefrom)
# include <fcntl.h> ])
COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }closefrom_test"
])
AC_CHECK_FUNCS([mkstemps mkdtemp], [], [break])
if test X"$ac_cv_func_mkstemps$ac_cv_func_mkdtemp" != X"yesyes"; then
sudo_mktemp=no
case "$host_os" in
darwin*)
# macOS has these but uses a _np (non-portable) suffix
AC_CHECK_FUNCS([mkdtempat_np mkostempsat_np], [], [sudo_mktemp=yes; break])
;;
*)
AC_CHECK_FUNCS([mkdtempat mkostempsat], [], [sudo_mktemp=yes; break])
;;
esac
# If any of the mktemp family are missing we use our own.
if test X"$sudo_mktemp" = X"yes"; then
AC_CHECK_FUNCS([arc4random random lrand48], [break])
if test X"$ac_cv_func_arc4random" != X"yes"; then
AC_CHECK_FUNCS([getentropy])
fi
AC_LIBOBJ(mktemp)
# If either mkdtemp() or mkstemps() is missing, replace both.
SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkstemps)
SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkdtempat sudo_mkostempsat sudo_mkstemp sudo_mkstemps)
COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }mktemp_test"
fi
AX_FUNC_SNPRINTF
@ -4995,7 +5016,7 @@ if test -n "$GCC"; then
dnl
dnl Default warnings for development use.
dnl
CFLAGS="${CFLAGS} -Wall -Wsign-compare -Wpointer-arith -Wno-unknown-pragmas"
CFLAGS="${CFLAGS} -Wall -Wsign-compare -Wpointer-arith -Wno-unknown-pragmas -Wmissing-prototypes -Wwrite-strings"
AX_CHECK_COMPILE_FLAG([-Wshadow], [CFLAGS="$CFLAGS -Wshadow"])
dnl
dnl The fallthrough attribute is supported by gcc 7.0 and clang 10.
@ -5032,7 +5053,7 @@ if test -n "$GCC"; then
if test X"$enable_werror" = X"yes"; then
CFLAGS="${CFLAGS} -Werror"
fi
case "$host" in
case "$host_os" in
# Avoid unwanted warnings on macOS
darwin*) CFLAGS="${CFLAGS} -Wno-deprecated-declarations";;
esac
@ -5525,7 +5546,53 @@ dnl
AH_TOP([#ifndef SUDO_CONFIG_H
#define SUDO_CONFIG_H])
AH_BOTTOM([/* Symbol visibility controls */
AH_BOTTOM([#ifndef __GNUC_PREREQ__
# ifdef __GNUC__
# define __GNUC_PREREQ__(ma, mi) \
((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
# else
# define __GNUC_PREREQ__(ma, mi) 0
# endif
#endif
/* Define away __attribute__ for non-gcc or old gcc. */
#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5)
# define __attribute__(x)
#endif
/* For functions that call exit() directly. */
#if __GNUC_PREREQ__(2, 5)
# define sudo_noreturn __attribute__((__noreturn__))
#else
# define sudo_noreturn
#endif
/* For malloc-like functions that return uninitialized or zeroed memory. */
#if __GNUC_PREREQ__(2, 96)
# define sudo_malloclike __attribute__((__malloc__))
#else
# define sudo_malloclike
#endif
/* Compile-time checking for function arguments that must not be NULL. */
#if __GNUC_PREREQ__(3, 3)
# define sudo_attr_nonnull(_a) __attribute__((__nonnull__ (_a)))
#else
# define sudo_attr_nonnull(_a)
#endif
/* For catching format string mismatches. */
#if __GNUC_PREREQ__(2, 7)
# define sudo_printflike(_f, _v) __attribute__((__format__ (__printf__, _f, _v))) sudo_attr_nonnull(_f)
# define sudo_printf0like(_f, _v) __attribute__((__format__ (__printf__, _f, _v)))
# define sudo_attr_fmt_arg(_f) __attribute__((__format_arg__ (_f)))
#else
# define sudo_printflike(_f, _v)
# define sudo_printf0like(_f, _v)
# define sudo_attr_fmt_arg(_f)
#endif
/* Symbol visibility controls. */
#ifdef HAVE_DSO_VISIBILITY
# if defined(__GNUC__)
# define sudo_dso_public __attribute__((__visibility__("default")))

View File

@ -25,6 +25,11 @@ Notes on upgrading from an older release
such as those seen with the Linux logrotate utility, which could
interpret a core dump as a valid configuration file.
To restore the historic core dump file size behavior, add the
following line to the sudoers file:
Defaults rlimit_core=default
* Upgrading from a version prior to 1.9.7:
Sudo now links with OpenSSL 1.0.1 or higher by default if it

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "CVTSUDOERS" "1" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "General Commands Manual"
.TH "CVTSUDOERS" "1" "September 29, 2022" "Sudo @PACKAGE_VERSION@" "General Commands Manual"
.nh
.if n .ad l
.SH "NAME"
@ -67,9 +67,8 @@ The options are as follows:
The base DN (distinguished name) that will be used when performing
LDAP queries.
Typically this is of the form
\fRou=SUDOers,dc=my-domain,dc=com\fR
for the domain
\fRmy-domain.com\fR.
\(lqou=SUDOers,dc=my-domain,dc=com\(rq
for the domain my-domain.com.
If this option is not specified, the value of the
\fRSUDOERS_BASE\fR
environment variable will be used instead.
@ -82,10 +81,10 @@ Defaults to
.TP 12n
\fB\-d\fR \fIdeftypes\fR, \fB\--defaults\fR=\fIdeftypes\fR
Only convert
\fRDefaults\fR
\fIDefaults\fR
entries of the specified types.
One or more
\fRDefaults\fR
\fIDefaults\fR
types may be specified, separated by a comma
(\(oq\&,\(cq).
The supported types are:
@ -122,7 +121,7 @@ for more information.
If the
\fB\-d\fR
option is not specified, all
\fRDefaults\fR
\fIDefaults\fR
entries will be converted.
.RE
.TP 12n
@ -143,12 +142,9 @@ The following formats are supported:
CSV
CSV (comma-separated value) files are often used by spreadsheets
and report generators.
For CSV output,
\fBcvtsudoers\fR
double quotes strings that contain commas.
For each literal double quote character present inside the string,
two double quotes are output.
This method of quoting commas is compatible with most spreadsheet programs.
See
\fICSV output format\fR
for more details.
.PD
.TP 10n
JSON
@ -160,6 +156,9 @@ The various values have explicit types which removes much of the
ambiguity of the
\fIsudoers\fR
format.
See
\fIJSON output format\fR
for more details.
.TP 10n
LDIF
LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
@ -264,7 +263,12 @@ For example,
\fBuser\fR = \fIoperator\fR
or
\fBhost\fR = \fIwww\fR.
An upper-case Cmnd_Alias, Host_alias, or Host_Alias may be specified as the
An upper-case
\fICmnd_Alias\fR,
\fIHost_alias\fR,
or
\fIUser_Alias\fR
may be specified as the
\(lqcmnd\(rq,
\(lqhost\(rq,
or
@ -436,7 +440,7 @@ Per-user rules are merged and duplicates are removed.
If a host name is specified with the input file,
\fBcvtsudoers\fR
will change rules that specify a host name of
\fRALL\fR
\fBALL\fR
to the host name associated with the policy file being merged.
The merging of rules is currently fairly simplistic but will be
improved in a later release.
@ -522,6 +526,754 @@ command line option.
.PP
Options on the command line will override values from the
configuration file.
.SS "JSON output format"
The
\fIsudoers\fR
JSON format may contain any of the following top-level objects:
.TP 6n
Defaults
An array of objects, each containing an
\fIOptions\fR
array and an optional
\fIBinding\fR
array.
.sp
The
\fIOptions\fR
array consists of one or more objects, each containing a
\(lqname:value\(rq
pair that corresponds to a
\fIsudoers\fR
\fIDefaults\fR
setting.
\fIOptions\fR
that operate on a list will also include an
\fIoperation\fR
entry in the object, with a value of
\(lqlist_assign\(rq
for
\(oq=\(cq,
\(lqlist_add\(rq
for
\(oq+=\(cq,
or
\(lqlist_remove\(rq
for
\(oq-=\(cq.
.sp
The optional
\fIBinding\fR
array consists of one or more objects, each containing a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
If a
\fIBinding\fR
is present, the setting will only take effect if one of the specified
\fIcommand\fR,
\fIhostname\fR,
\fInetgroup\fR,
\fInetworkaddr\fR,
\fInonunixgid\fR,
\fInonunixgroup\fR,
\fIusergid\fR,
\fIusergroup\fR,
\fIuserid\fR,
\fIusername\fR,
or alias entries match.
.sp
For example, the following
\fIsudoers\fR
entry:
.nf
.sp
.RS 6n
Defaults@somehost set_home, env_keep += DISPLAY
.RE
.fi
.RS 6n
.sp
converts to:
.nf
.sp
.RS 6n
"Defaults": [
{
"Binding": [
{ "hostname": "somehost" }
],
"Options": [
{ "set_home": true },
{
"operation": "list_add",
"env_keep": [
"DISPLAY"
]
}
]
}
]
.RE
.fi
.RE
.TP 6n
User_Aliases
A JSON object containing one or more
\fIsudoers\fR
\fIUser_Alias\fR
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fInetgroup\fR,
\fInonunixgid\fR,
\fInonunixgroup\fR,
\fIuseralias\fR,
\fIusergid\fR,
\fIusergroup\fR,
\fIuserid\fR,
or
\fIusername\fR.
.sp
For example, the following
\fIsudoers\fR
entry:
.nf
.sp
.RS 6n
User_Alias SYSADMIN = will, %wheel, +admin
.RE
.fi
.RS 6n
.sp
converts to:
.nf
.sp
.RS 6n
"User_Aliases": {
"SYSADMIN": [
{ "username": "will" },
{ "usergroup": "wheel" },
{ "netgroup": "admin" }
]
}
.RE
.fi
.RE
.TP 6n
Runas_Aliases
A JSON object containing one or more
\fIsudoers\fR
\fIRunas_Alias\fR
entries, where each named alias has as its value an array
containing one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fInetgroup\fR,
\fInonunixgid\fR,
\fInonunixgroup\fR,
\fIrunasalias\fR,
\fIusergid\fR,
\fIusergroup\fR,
\fIuserid\fR,
or
\fIusername\fR.
.sp
For example, the following
\fIsudoers\fR
entry:
.nf
.sp
.RS 6n
Runas_Alias DB = oracle, sybase : OP = root, operator
.RE
.fi
.RS 6n
.sp
converts to:
.nf
.sp
.RS 6n
"Runas_Aliases": {
"DB": [
{ "username": "oracle" },
{ "username": "sybase" }
],
"OP": [
{ "username": "root" },
{ "username": "operator" }
]
}
.RE
.fi
.RE
.TP 6n
Host_Aliases
A JSON object containing one or more
\fIsudoers\fR
\fIHost_Alias\fR
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fIhostalias\fR,
\fIhostname\fR,
\fInetgroup\fR,
or
\fInetworkaddr\fR.
.sp
For example, the following
\fIsudoers\fR
entries:
.nf
.sp
.RS 6n
Host_Alias DORMNET = 128.138.243.0, 128.138.204.0/24
Host_Alias SERVERS = boulder, refuge
.RE
.fi
.RS 6n
.sp
convert to:
.nf
.sp
.RS 6n
"Host_Aliases": {
"DORMNET": [
{ "networkaddr": "128.138.243.0" },
{ "networkaddr": "128.138.204.0/24" }
],
"SERVERS": [
{ "hostname": "boulder" },
{ "hostname": "refuge" }
]
}
.RE
.fi
.RE
.TP 6n
Cmnd_Aliases
A JSON object containing one or more
\fIsudoers\fR
\fICmnd_Alias\fR
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be either another
\fIcmndalias\fR
or a
\fIcommand\fR.
For example, the following
\fIsudoers\fR
entries:
.nf
.sp
.RS 6n
Cmnd_Alias SHELLS = /bin/bash, /bin/csh, /bin/sh, /bin/zsh
Cmnd_Alias VIPW = /usr/bin/chpass, /usr/bin/chfn, /usr/bin/chsh, \e
/usr/bin/passwd, /usr/sbin/vigr, /usr/sbin/vipw
.RE
.fi
.RS 6n
.sp
convert to:
.nf
.sp
.RS 6n
"Cmnd_Aliases": {
"SHELLS": [
{ "command": "/bin/bash" },
{ "command": "/bin/csh" },
{ "command": "/bin/sh" },
{ "command": "/bin/zsh" }
],
"VIPW": [
{ "command": "/usr/bin/chpass" },
{ "command": "/usr/bin/chfn" },
{ "command": "/usr/bin/chsh" },
{ "command": "/usr/bin/passwd" },
{ "command": "/usr/sbin/vigr" },
{ "command": "/usr/sbin/vipw" }
]
}
.RE
.fi
.RE
.TP 6n
User_Specs
A JSON array containing one or more objects, each representing a
\fIsudoers\fR
User_Spec.
Each object in the
\fIUser_Specs\fR
array should contain a
\fIUser_List\fR
array, a
\fIHost_List\fR
array and a
\fICmnd_Specs\fR
array.
.sp
A
\fIUser_List\fR
consists of one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fInetgroup\fR,
\fInonunixgid\fR,
\fInonunixgroup\fR,
\fIuseralias\fR,
\fIusergid\fR,
\fIusergroup\fR,
\fIuserid\fR,
or
\fIusername\fR.
If
\fIusername\fR
is set to the special value
\fBALL\fR,
it will match any user.
.sp
A
\fIHost_List\fR
consists of one or more objects.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fIhostalias\fR,
\fIhostname\fR,
\fInetgroup\fR,
or
\fInetworkaddr\fR.
If
\fIhostname\fR
is set to the special value
\fBALL\fR,
it will match any host.
.sp
The
\fICmnd_Specs\fR
array consists of one or more JSON objects describing a command that
may be run.
Each
\fICmnd_Specs\fR
is made up of a
\fICommands\fR
array, an optional
\fIrunasusers\fR
array, an optional
\fIrunasgroups\fR
array, and an optional
\fIOptions array.\fR
.sp
The
\fICommands\fR
array consists of one or more objects containing
\(lqname:value\(rq
pair elements.
The following names and values are supported:
.PP
.RS 6n
.PD 0
.TP 10n
command
A string containing the command to run.
The special value
\fBALL\fR
it will match any command.
.PD
.TP 10n
negated
A boolean value that, if true, will negate any comparison performed
with the object.
.TP 10n
sha224
A string containing the SHA224 digest of the
\fIcommand\fR.
.TP 10n
sha256
A string containing the SHA256 digest of the
\fIcommand\fR.
.TP 10n
sha384
A string containing the SHA384 digest of the
\fIcommand\fR.
.TP 10n
sha512
A string containing the SHA512 digest of the
\fIcommand\fR.
.PP
The
\fIrunasusers\fR
array consists of objects describing users the command may be run as.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fInetgroup\fR,
\fInonunixgid\fR,
\fInonunixgroup\fR,
\fIrunasalias\fR,
\fIusergid\fR,
\fIusergroup\fR,
\fIuserid\fR,
or
\fIusername\fR.
If
\fIusername\fR
is set to the special value
\fBALL\fR,
it will match any user.
If
\fIusername\fR
is set to the empty string
\(lq\(rq,
it will match the invoking user.
.sp
The
\fIrunasgroups\fR
array consists of objects describing groups the command may be run as.
Each object contains a
\(lqname:value\(rq
pair and an optional
\fInegated\fR
entry, which will negate any comparison performed with the object.
The name may be one of
\fIrunasalias\fR,
\fIusergid\fR,
or
\fIusergroup\fR.
If
\fIusergroup\fR
is set to the special value
\fBALL\fR,
it will match any group.
.sp
The
\fIOptions\fR
array is of the same format as the one in the
\fIDefaults\fR
object.
Any
\fITag_Spec\fR
entries in
\fIsudoers\fR
are converted to
\fIOptions\fR.
A user with
\(lqsudo ALL\(rq
privileges will automatically have the
\fIsetenv\fR
option enabled to match the implicit behavior provided by
\fIsudoers\fR.
.sp
For example, the following
\fIsudoers\fR
entry:
.nf
.sp
.RS 6n
millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
.RE
.fi
.sp
converts to:
.nf
.sp
.RS 6n
"User_Specs": [
{
"User_List": [
{ "username": "millert" }
],
"Host_List": [
{ "hostname": "ALL" }
],
"Cmnd_Specs": [
{
"runasusers": [
{ "username": "ALL" }
],
"runasgroups": [
{ "usergroup": "ALL" }
],
"Options": [
{ "authenticate": false },
{ "setenv": true }
],
"Commands": [
{ "command": "ALL" },
{
"command": "/usr/bin/id",
"negated": true
}
]
}
]
}
]
.RE
.fi
.RE
.SS "CSV output format"
CSV (comma-separated value) files are often used by spreadsheets
and report generators.
For CSV output,
\fBcvtsudoers\fR
double quotes strings that contain commas.
For each literal double quote character present inside the string,
two double quotes are output.
This method of quoting commas is compatible with most spreadsheet programs.
.PP
There are three possible sections in
\fBcvtsudoers\fR's
CSV output, each separated by a blank line:
.TP 6n
defaults
This section includes any
\fIDefaults\fR
settings in
\fIsudoers\fR.
The
\fIdefaults\fR
section begins with the following heading:
.nf
.sp
.RS 12n
defaults_type,binding,name,operator,value
.RE
.fi
.RS 6n
.sp
The fields are as follows:
.TP 10n
defaults_type
The type of
\fIDefaults\fR
setting; one of
\fIdefaults\fR,
\fIdefaults_command\fR,
\fIdefaults_host\fR,
\fIdefaults_runas\fR,
or
\fIdefaults_user\fR.
.TP 10n
binding
For
\fIdefaults_command\fR,
\fIdefaults_host\fR,
\fIdefaults_runas\fR,
and
\fIdefaults_user\fR
this is the value that must match for the setting to be applied.
.TP 10n
name
The name of the
\fIDefaults\fR
setting.
.TP 10n
operator
The operator determines how the value is applied to the setting.
It may be either
\(oq=\(cq
(assignment),
\(oq+=\(cq
(append),
or
\(oq-=\(cq
(remove).
.TP 10n
value
The setting's value, usually a string or, for
settings used in a boolean context,
\fItrue\fR
or
\fIfalse\fR.
.PD 0
.PP
.RE
.PD
.TP 6n
aliases
This section includes any
\fICmnd_Alias\fR
\fIHost_Alias\fR,
\fIRunas_Alias\fR,
or
\fIUser_Alias\fR,
entries from
\fIsudoers\fR.
The
\fIaliases\fR
section begins with the following heading:
.nf
.sp
.RS 12n
alias_type,alias_name,members
.RE
.fi
.RS 6n
.sp
The fields are as follows:
.TP 10n
alias_type
The type of alias; one of
\fICmnd_Alias\fR,
\fIHost_Alias\fR,
\fIRunas_Alias\fR,
or
\fIUser_Alias\fR.
.TP 10n
alias_name
The name of the alias; a string starting with an upper-case letter that
consists of upper-case letters, digits, or underscores.
.TP 10n
members
A comma-separated list of members belonging to the alias.
Due to the use of commas,
\fImembers\fR
is surrounded by double quotes if it contains more than one member.
.PD 0
.PP
.RE
.PD
.TP 6n
rules
.br
This section includes the
\fIsudoers\fR
rules that grant privileges.
The
\fIrules\fR
section begins with the following heading:
.nf
.sp
.RS 12n
rule,user,host,runusers,rungroups,options,command
.RE
.fi
.RS 6n
.sp
The fields are as follows:
.TP 10n
rule
This field indicates a
\fIsudoers\fR
\fIrule\fR
entry.
.TP 10n
user
The user the rule applies to.
This may also be a Unix group (preceded by a
\(oq%\(cq
character), a non-Unix group (preceded by
\(oq%:\(cq)
or a netgroup (preceded by a
\(oq+\(cq
character)
or a
\fIUser_Alias\fR.
If set to the special value
\fBALL\fR,
it will match any user.
.TP 10n
host
The host the rule applies to.
This may also be a netgroup (preceded by a
\(oq+\(cq
character)
or a
\fIHost_Alias\fR.
If set to the special value
\fBALL\fR,
it will match any host.
.TP 10n
runusers
An optional comma-separated list of users (or
\fIRunas_Alias\fRes)
the command may be run as.
If it contains more than one member, the value is surrounded by
double quotes.
If set to the special value
\fBALL\fR,
it will match any user.
If empty, the root user is assumed.
.TP 10n
rungroups
.br
An optional comma-separated list of groups (or
\fIRunas_Alias\fRes)
the command may be run as.
If it contains more than one member, the value is surrounded by
double quotes.
If set to the special value
\fBALL\fR,
it will match any group.
If empty, the
\fIrunuser\fR's
group is used.
.TP 10n
options
An optional list of
\fIDefaults\fR
settings to apply to the command.
Any
\fITag_Spec\fR
entries in
\fIsudoers\fR
are converted to
\fIoptions\fR.
.TP 10n
commands
A list of commands, with optional arguments, that the user is allowed to run.
If set to the special value
\fBALL\fR,
it will match any command.
.PP
For example, the following
\fIsudoers\fR
entry:
.nf
.sp
.RS 6n
millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
.RE
.fi
.sp
converts to:
.nf
.sp
.RS 6n
rule,millert,ALL,ALL,ALL,"!authenticate","ALL,!/usr/bin/id"
.RE
.fi
.RE
.SH "FILES"
.TP 26n
\fI@sysconfdir@/cvtsudoers.conf\fR

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 29, 2022
.Dt CVTSUDOERS 1
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -65,9 +65,8 @@ The options are as follows:
The base DN (distinguished name) that will be used when performing
LDAP queries.
Typically this is of the form
.Li ou=SUDOers,dc=my-domain,dc=com
for the domain
.Li my-domain.com .
.Dq ou=SUDOers,dc=my-domain,dc=com
for the domain my-domain.com.
If this option is not specified, the value of the
.Ev SUDOERS_BASE
environment variable will be used instead.
@ -78,10 +77,10 @@ Defaults to
.Pa @sysconfdir@/cvtsudoers.conf .
.It Fl d Ar deftypes , Fl -defaults Ns = Ns Ar deftypes
Only convert
.Li Defaults
.Em Defaults
entries of the specified types.
One or more
.Li Defaults
.Em Defaults
types may be specified, separated by a comma
.Pq Ql \&, .
The supported types are:
@ -110,7 +109,7 @@ for more information.
If the
.Fl d
option is not specified, all
.Li Defaults
.Em Defaults
entries will be converted.
.It Fl e , Fl -expand-aliases
Expand aliases in
@ -125,12 +124,9 @@ The following formats are supported:
.It CSV
CSV (comma-separated value) files are often used by spreadsheets
and report generators.
For CSV output,
.Nm
double quotes strings that contain commas.
For each literal double quote character present inside the string,
two double quotes are output.
This method of quoting commas is compatible with most spreadsheet programs.
See
.Sx CSV output format
for more details.
.It JSON
JSON (JavaScript Object Notation) files are usually easier for
third-party applications to consume than the traditional
@ -140,6 +136,9 @@ The various values have explicit types which removes much of the
ambiguity of the
.Em sudoers
format.
See
.Sx JSON output format
for more details.
.It LDIF
LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
server for use with
@ -217,7 +216,12 @@ For example,
.Sy user No = Ar operator
or
.Sy host No = Ar www .
An upper-case Cmnd_Alias, Host_alias, or Host_Alias may be specified as the
An upper-case
.Em Cmnd_Alias ,
.Em Host_alias ,
or
.Em User_Alias
may be specified as the
.Dq cmnd ,
.Dq host ,
or
@ -360,9 +364,9 @@ subsequent aliases of the same name are renamed with a numeric suffix
separated with a underscore
.Pq Ql _ .
For example, if there are two different aliases named
.Li SERVERS ,
.Dv SERVERS ,
the first will be left as-is and the second will be renamed
.Li SERVERS_1 .
.Dv SERVERS_1 .
References to the renamed alias are also updated in the policy file.
Duplicate aliases (those with identical contents) are pruned.
.It
@ -379,7 +383,7 @@ Per-user rules are merged and duplicates are removed.
If a host name is specified with the input file,
.Nm
will change rules that specify a host name of
.Li ALL
.Sy ALL
to the host name associated with the policy file being merged.
The merging of rules is currently fairly simplistic but will be
improved in a later release.
@ -454,6 +458,656 @@ command line option.
.Pp
Options on the command line will override values from the
configuration file.
.Ss JSON output format
The
.Em sudoers
JSON format may contain any of the following top-level objects:
.Bl -tag -width 4n
.It Defaults
An array of objects, each containing an
.Em Options
array and an optional
.Em Binding
array.
.Pp
The
.Em Options
array consists of one or more objects, each containing a
.Dq name:value
pair that corresponds to a
.Em sudoers
.Em Defaults
setting.
.Em Options
that operate on a list will also include an
.Em operation
entry in the object, with a value of
.Dq list_assign
for
.Ql = ,
.Dq list_add
for
.Ql += ,
or
.Dq list_remove
for
.Ql -= .
.Pp
The optional
.Em Binding
array consists of one or more objects, each containing a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
If a
.Em Binding
is present, the setting will only take effect if one of the specified
.Em command ,
.Em hostname ,
.Em netgroup ,
.Em networkaddr ,
.Em nonunixgid ,
.Em nonunixgroup ,
.Em usergid ,
.Em usergroup ,
.Em userid ,
.Em username ,
or alias entries match.
.Pp
For example, the following
.Em sudoers
entry:
.Bd -literal
Defaults@somehost set_home, env_keep += DISPLAY
.Ed
.Pp
converts to:
.Bd -literal
"Defaults": [
{
"Binding": [
{ "hostname": "somehost" }
],
"Options": [
{ "set_home": true },
{
"operation": "list_add",
"env_keep": [
"DISPLAY"
]
}
]
}
]
.Ed
.It User_Aliases
A JSON object containing one or more
.Em sudoers
.Em User_Alias
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em netgroup ,
.Em nonunixgid ,
.Em nonunixgroup ,
.Em useralias ,
.Em usergid ,
.Em usergroup ,
.Em userid ,
or
.Em username .
.Pp
For example, the following
.Em sudoers
entry:
.Bd -literal
User_Alias SYSADMIN = will, %wheel, +admin
.Ed
.Pp
converts to:
.Bd -literal
"User_Aliases": {
"SYSADMIN": [
{ "username": "will" },
{ "usergroup": "wheel" },
{ "netgroup": "admin" }
]
}
.Ed
.It Runas_Aliases
A JSON object containing one or more
.Em sudoers
.Em Runas_Alias
entries, where each named alias has as its value an array
containing one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em netgroup ,
.Em nonunixgid ,
.Em nonunixgroup ,
.Em runasalias ,
.Em usergid ,
.Em usergroup ,
.Em userid ,
or
.Em username .
.Pp
For example, the following
.Em sudoers
entry:
.Bd -literal
Runas_Alias DB = oracle, sybase : OP = root, operator
.Ed
.Pp
converts to:
.Bd -literal
"Runas_Aliases": {
"DB": [
{ "username": "oracle" },
{ "username": "sybase" }
],
"OP": [
{ "username": "root" },
{ "username": "operator" }
]
}
.Ed
.It Host_Aliases
A JSON object containing one or more
.Em sudoers
.Em Host_Alias
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em hostalias ,
.Em hostname ,
.Em netgroup ,
or
.Em networkaddr .
.Pp
For example, the following
.Em sudoers
entries:
.Bd -literal
Host_Alias DORMNET = 128.138.243.0, 128.138.204.0/24
Host_Alias SERVERS = boulder, refuge
.Ed
.Pp
convert to:
.Bd -literal
"Host_Aliases": {
"DORMNET": [
{ "networkaddr": "128.138.243.0" },
{ "networkaddr": "128.138.204.0/24" }
],
"SERVERS": [
{ "hostname": "boulder" },
{ "hostname": "refuge" }
]
}
.Ed
.It Cmnd_Aliases
A JSON object containing one or more
.Em sudoers
.Em Cmnd_Alias
entries where each named alias has as its value an array
containing one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be either another
.Em cmndalias
or a
.Em command .
For example, the following
.Em sudoers
entries:
.Bd -literal
Cmnd_Alias SHELLS = /bin/bash, /bin/csh, /bin/sh, /bin/zsh
Cmnd_Alias VIPW = /usr/bin/chpass, /usr/bin/chfn, /usr/bin/chsh, \e
/usr/bin/passwd, /usr/sbin/vigr, /usr/sbin/vipw
.Ed
.Pp
convert to:
.Bd -literal
"Cmnd_Aliases": {
"SHELLS": [
{ "command": "/bin/bash" },
{ "command": "/bin/csh" },
{ "command": "/bin/sh" },
{ "command": "/bin/zsh" }
],
"VIPW": [
{ "command": "/usr/bin/chpass" },
{ "command": "/usr/bin/chfn" },
{ "command": "/usr/bin/chsh" },
{ "command": "/usr/bin/passwd" },
{ "command": "/usr/sbin/vigr" },
{ "command": "/usr/sbin/vipw" }
]
}
.Ed
.It User_Specs
A JSON array containing one or more objects, each representing a
.Em sudoers
User_Spec.
Each object in the
.Em User_Specs
array should contain a
.Em User_List
array, a
.Em Host_List
array and a
.Em Cmnd_Specs
array.
.Pp
A
.Em User_List
consists of one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em netgroup ,
.Em nonunixgid ,
.Em nonunixgroup ,
.Em useralias ,
.Em usergid ,
.Em usergroup ,
.Em userid ,
or
.Em username .
If
.Em username
is set to the special value
.Sy ALL ,
it will match any user.
.Pp
A
.Em Host_List
consists of one or more objects.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em hostalias ,
.Em hostname ,
.Em netgroup ,
or
.Em networkaddr .
If
.Em hostname
is set to the special value
.Sy ALL ,
it will match any host.
.Pp
The
.Em Cmnd_Specs
array consists of one or more JSON objects describing a command that
may be run.
Each
.Em Cmnd_Specs
is made up of a
.Em Commands
array, an optional
.Em runasusers
array, an optional
.Em runasgroups
array, and an optional
.Em Options array.
.Pp
The
.Em Commands
array consists of one or more objects containing
.Dq name:value
pair elements.
The following names and values are supported:
.Bl -tag -width 8n
.It command
A string containing the command to run.
The special value
.Sy ALL
it will match any command.
.It negated
A boolean value that, if true, will negate any comparison performed
with the object.
.It sha224
A string containing the SHA224 digest of the
.Em command .
.It sha256
A string containing the SHA256 digest of the
.Em command .
.It sha384
A string containing the SHA384 digest of the
.Em command .
.It sha512
A string containing the SHA512 digest of the
.Em command .
.El
.Pp
The
.Em runasusers
array consists of objects describing users the command may be run as.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em netgroup ,
.Em nonunixgid ,
.Em nonunixgroup ,
.Em runasalias ,
.Em usergid ,
.Em usergroup ,
.Em userid ,
or
.Em username .
If
.Em username
is set to the special value
.Sy ALL ,
it will match any user.
If
.Em username
is set to the empty string
.Dq "" ,
it will match the invoking user.
.Pp
The
.Em runasgroups
array consists of objects describing groups the command may be run as.
Each object contains a
.Dq name:value
pair and an optional
.Em negated
entry, which will negate any comparison performed with the object.
The name may be one of
.Em runasalias ,
.Em usergid ,
or
.Em usergroup .
If
.Em usergroup
is set to the special value
.Sy ALL ,
it will match any group.
.Pp
The
.Em Options
array is of the same format as the one in the
.Em Defaults
object.
Any
.Em Tag_Spec
entries in
.Em sudoers
are converted to
.Em Options .
A user with
.Dq sudo ALL
privileges will automatically have the
.Em setenv
option enabled to match the implicit behavior provided by
.Em sudoers .
.Pp
For example, the following
.Em sudoers
entry:
.Bd -literal
millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
.Ed
.Pp
converts to:
.Bd -literal
"User_Specs": [
{
"User_List": [
{ "username": "millert" }
],
"Host_List": [
{ "hostname": "ALL" }
],
"Cmnd_Specs": [
{
"runasusers": [
{ "username": "ALL" }
],
"runasgroups": [
{ "usergroup": "ALL" }
],
"Options": [
{ "authenticate": false },
{ "setenv": true }
],
"Commands": [
{ "command": "ALL" },
{
"command": "/usr/bin/id",
"negated": true
}
]
}
]
}
]
.Ed
.El
.Ss CSV output format
CSV (comma-separated value) files are often used by spreadsheets
and report generators.
For CSV output,
.Nm
double quotes strings that contain commas.
For each literal double quote character present inside the string,
two double quotes are output.
This method of quoting commas is compatible with most spreadsheet programs.
.Pp
There are three possible sections in
.Nm cvtsudoers Ns 's
CSV output, each separated by a blank line:
.Bl -tag -width 4n
.It defaults
This section includes any
.Em Defaults
settings in
.Em sudoers .
The
.Em defaults
section begins with the following heading:
.Bd -literal -offset indent
defaults_type,binding,name,operator,value
.Ed
.Pp
The fields are as follows:
.Bl -tag -width 8n
.It defaults_type
The type of
.Em Defaults
setting; one of
.Em defaults ,
.Em defaults_command ,
.Em defaults_host ,
.Em defaults_runas ,
or
.Em defaults_user .
.It binding
For
.Em defaults_command ,
.Em defaults_host ,
.Em defaults_runas ,
and
.Em defaults_user
this is the value that must match for the setting to be applied.
.It name
The name of the
.Em Defaults
setting.
.It operator
The operator determines how the value is applied to the setting.
It may be either
.Ql =
(assignment),
.Ql +=
(append),
or
.Ql -=
(remove).
.It value
The setting's value, usually a string or, for
settings used in a boolean context,
.Em true
or
.Em false .
.El
.It aliases
This section includes any
.Em Cmnd_Alias
.Em Host_Alias ,
.Em Runas_Alias ,
or
.Em User_Alias ,
entries from
.Em sudoers .
The
.Em aliases
section begins with the following heading:
.Bd -literal -offset indent
alias_type,alias_name,members
.Ed
.Pp
The fields are as follows:
.Bl -tag -width 8n
.It alias_type
The type of alias; one of
.Em Cmnd_Alias ,
.Em Host_Alias ,
.Em Runas_Alias ,
or
.Em User_Alias .
.It alias_name
The name of the alias; a string starting with an upper-case letter that
consists of upper-case letters, digits, or underscores.
.It members
A comma-separated list of members belonging to the alias.
Due to the use of commas,
.Em members
is surrounded by double quotes if it contains more than one member.
.El
.It rules
This section includes the
.Em sudoers
rules that grant privileges.
The
.Em rules
section begins with the following heading:
.Bd -literal -offset indent
rule,user,host,runusers,rungroups,options,command
.Ed
.Pp
The fields are as follows:
.Bl -tag -width 8n
.It rule
This field indicates a
.Em sudoers
.Em rule
entry.
.It user
The user the rule applies to.
This may also be a Unix group (preceded by a
.Ql %
character), a non-Unix group (preceded by
.Ql %: )
or a netgroup (preceded by a
.Ql +
character)
or a
.Em User_Alias .
If set to the special value
.Sy ALL ,
it will match any user.
.It host
The host the rule applies to.
This may also be a netgroup (preceded by a
.Ql +
character)
or a
.Em Host_Alias .
If set to the special value
.Sy ALL ,
it will match any host.
.It runusers
An optional comma-separated list of users (or
.Em Runas_Alias Ns No es )
the command may be run as.
If it contains more than one member, the value is surrounded by
double quotes.
If set to the special value
.Sy ALL ,
it will match any user.
If empty, the root user is assumed.
.It rungroups
An optional comma-separated list of groups (or
.Em Runas_Alias Ns No es )
the command may be run as.
If it contains more than one member, the value is surrounded by
double quotes.
If set to the special value
.Sy ALL ,
it will match any group.
If empty, the
.Em runuser Ns 's
group is used.
.It options
An optional list of
.Em Defaults
settings to apply to the command.
Any
.Em Tag_Spec
entries in
.Em sudoers
are converted to
.Em options .
.It commands
A list of commands, with optional arguments, that the user is allowed to run.
If set to the special value
.Sy ALL ,
it will match any command.
.El
.Pp
For example, the following
.Em sudoers
entry:
.Bd -literal
millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
.Ed
.Pp
converts to:
.Bd -literal
rule,millert,ALL,ALL,ALL,"!authenticate","ALL,!/usr/bin/id"
.Ed
.El
.Sh FILES
.Bl -tag -width 24n
.It Pa @sysconfdir@/cvtsudoers.conf

View File

@ -7,9 +7,9 @@
attributetype ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SUBSTR caseExactSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
@ -39,14 +39,14 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.5
attributetype ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'

View File

@ -1,11 +1,11 @@
dn: cn=schema
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactMatch SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributeTypes: ( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )

View File

@ -9,9 +9,9 @@ cn: sudoschema
olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SUBSTR caseExactSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
#
olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
@ -41,14 +41,14 @@ olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.5
olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
#
olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
#
olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'

View File

@ -70,17 +70,17 @@ Leading white space is removed from the beginning of lines
even when a continuation character is used.
.PP
Non-comment lines that don't begin with
\fRPlugin\fR,
\fRPath\fR,
\fRDebug\fR,
\fIPlugin\fR,
\fIPath\fR,
\fIDebug\fR,
or
\fRSet\fR
\fISet\fR
are silently ignored.
.PP
The
\fBsudo.conf\fR
file is always parsed in the
\(lq\fRC\fR\(rq
\(oqC\(cq
locale.
.SS "Plugin configuration"
\fBsudo\fR
@ -94,9 +94,9 @@ Plugins are dynamically loaded based on the contents of
\fBsudo.conf\fR.
.PP
A
\fRPlugin\fR
\fIPlugin\fR
line consists of the
\fRPlugin\fR
\fIPlugin\fR
keyword, followed by the
\fIsymbol_name\fR
and the
@ -105,14 +105,14 @@ to the dynamic shared object that contains the plugin.
The
\fIsymbol_name\fR
is the name of the
\fRapproval_plugin\fR,
\fRaudit_plugin\fR,
\fRio_plugin\fR,
\fIstruct approval_plugin\fR,
\fIstruct audit_plugin\fR,
\fIstruct io_plugin\fR,
or
\fRpolicy_plugin\fR
struct contained in the plugin.
\fIstruct policy_plugin\fR
defined by the plugin.
If a plugin implements multiple plugin types, there must be a
\fRPlugin\fR
\fIPlugin\fR
line for each unique symbol name.
The
\fIpath\fR
@ -120,7 +120,7 @@ may be fully qualified or relative.
If not fully qualified, it is relative to the directory
specified by the
\fIplugin_dir\fR
\fRPath\fR
\fIPath\fR
setting, which defaults to
\fI@plugindir@\fR.
In other words:
@ -182,7 +182,7 @@ This limitation does not apply to I/O plugins.
If no
\fBsudo.conf\fR
file is present, or if it contains no
\fRPlugin\fR
\fIPlugin\fR
lines, the
\fBsudoers\fR
plugin will be used as the default security policy, for I/O logging
@ -221,9 +221,9 @@ sudo_plugin(@mansectform@)
manual.
.SS "Path settings"
A
\fRPath\fR
\fIPath\fR
line consists of the
\fRPath\fR
\fIPath\fR
keyword, followed by the name of the path to set and its value.
For example:
.nf
@ -238,7 +238,7 @@ Path askpass /usr/X11R6/bin/ssh-askpass
If no path name is specified, features relying on the specified
setting will be disabled.
Disabling
\fRPath\fR
\fIPath\fR
settings is only supported in
\fBsudo\fR
version 1.8.16 and higher.
@ -277,7 +277,7 @@ If terminal devices may be located in a sub-directory of
that path must be explicitly listed in
\fIdevsearch\fR.
The default value is
\fR/dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev\fR
\fI/dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev\fR
.sp
This option is ignored on systems that support either the
\fBdevname\fR()
@ -290,15 +290,15 @@ macOS and Solaris.
intercept
.br
The fully-qualified path to a shared library containing a wrappers for the
\fBexecl\fR(),
\fBexecle\fR(),
\fBexeclp\fR(),
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
execve(2),
execl(3),
execle(3),
execlp(3),
execv(3),
execvp(3),
execvpe(3),
and
\fBsystem\fR()
system(3)
library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the
@ -312,23 +312,23 @@ The default value is
noexec
The fully-qualified path to a shared library containing wrappers
for the
\fBexecl\fR(),
\fBexecle\fR(),
\fBexeclp\fR(),
\fBexect\fR(),
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecveat\fR(),
\fBexecvP\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
\fBfexecve\fR(),
\fBpopen\fR(),
\fBposix_spawn\fR(),
\fBposix_spawnp\fR(),
\fBsystem\fR(),
execve(2),
execl(3),
execle(3),
execlp(3),
exect(3),
execv(3),
execveat(3),
execvP(3),
execvp(3),
execvpe(3),
fexecve(3),
popen(3),
posix_spawn(3),
posix_spawnp(3),
system(3),
and
\fBwordexp\fR()
wordexp(3)
library functions that prevent the execution of further commands.
This is used to implement the
\fInoexec\fR
@ -569,9 +569,9 @@ that can log what
is doing internally if there is a problem.
.PP
A
\fRDebug\fR
\fIDebug\fR
line consists of the
\fRDebug\fR
\fIDebug\fR
keyword, followed by the name of the program, plugin, or shared object
to debug, the debug file name, and a comma-separated list of debug flags.
The debug flag syntax used by
@ -613,25 +613,25 @@ intercept functionality on some systems.
As of
\fBsudo\fR
1.8.12, multiple
\fRDebug\fR
\fIDebug\fR
entries may be specified per program.
Older versions of
\fBsudo\fR
only support a single
\fRDebug\fR
\fIDebug\fR
entry per program.
Plugin-specific
\fRDebug\fR
\fIDebug\fR
entries are also supported starting with
\fBsudo\fR
1.8.12 and are matched by either the base name of the plugin that was loaded
(for example
\fRsudoers.so\fR)
\fIsudoers.so\fR)
or by the plugin's fully-qualified path name.
Previously, the
\fBsudoers\fR
plugin shared the same
\fRDebug\fR
\fIDebug\fR
entry as the
\fBsudo\fR
front-end and could not be configured separately.

View File

@ -67,17 +67,17 @@ Leading white space is removed from the beginning of lines
even when a continuation character is used.
.Pp
Non-comment lines that don't begin with
.Li Plugin ,
.Li Path ,
.Li Debug ,
.Em Plugin ,
.Em Path ,
.Em Debug ,
or
.Li Set
.Em Set
are silently ignored.
.Pp
The
.Nm
file is always parsed in the
.Dq Li C
.Ql C
locale.
.Ss Plugin configuration
.Nm sudo
@ -91,9 +91,9 @@ Plugins are dynamically loaded based on the contents of
.Nm .
.Pp
A
.Li Plugin
.Em Plugin
line consists of the
.Li Plugin
.Em Plugin
keyword, followed by the
.Em symbol_name
and the
@ -102,14 +102,14 @@ to the dynamic shared object that contains the plugin.
The
.Em symbol_name
is the name of the
.Li approval_plugin ,
.Li audit_plugin ,
.Li io_plugin ,
.Vt struct approval_plugin ,
.Vt struct audit_plugin ,
.Vt struct io_plugin ,
or
.Li policy_plugin
struct contained in the plugin.
.Vt struct policy_plugin
defined by the plugin.
If a plugin implements multiple plugin types, there must be a
.Li Plugin
.Em Plugin
line for each unique symbol name.
The
.Em path
@ -117,7 +117,7 @@ may be fully qualified or relative.
If not fully qualified, it is relative to the directory
specified by the
.Em plugin_dir
.Li Path
.Em Path
setting, which defaults to
.Pa @plugindir@ .
In other words:
@ -167,7 +167,7 @@ This limitation does not apply to I/O plugins.
If no
.Nm
file is present, or if it contains no
.Li Plugin
.Em Plugin
lines, the
.Nm sudoers
plugin will be used as the default security policy, for I/O logging
@ -203,9 +203,9 @@ plugin architecture, see the
manual.
.Ss Path settings
A
.Li Path
.Em Path
line consists of the
.Li Path
.Em Path
keyword, followed by the name of the path to set and its value.
For example:
.Bd -literal -offset 4n
@ -217,7 +217,7 @@ Path askpass /usr/X11R6/bin/ssh-askpass
If no path name is specified, features relying on the specified
setting will be disabled.
Disabling
.Li Path
.Em Path
settings is only supported in
.Nm sudo
version 1.8.16 and higher.
@ -254,7 +254,7 @@ If terminal devices may be located in a sub-directory of
that path must be explicitly listed in
.Em devsearch .
The default value is
.Li /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
.Pa /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
.Pp
This option is ignored on systems that support either the
.Fn devname
@ -265,15 +265,15 @@ functions, for example
macOS and Solaris.
.It intercept
The fully-qualified path to a shared library containing a wrappers for the
.Fn execl ,
.Fn execle ,
.Fn execlp ,
.Fn execv ,
.Fn execve ,
.Fn execvp ,
.Fn execvpe ,
.Xr execve 2 ,
.Xr execl 3 ,
.Xr execle 3 ,
.Xr execlp 3 ,
.Xr execv 3 ,
.Xr execvp 3 ,
.Xr execvpe 3 ,
and
.Fn system
.Xr system 3
library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the
@ -286,23 +286,23 @@ The default value is
.It noexec
The fully-qualified path to a shared library containing wrappers
for the
.Fn execl ,
.Fn execle ,
.Fn execlp ,
.Fn exect ,
.Fn execv ,
.Fn execve ,
.Fn execveat ,
.Fn execvP ,
.Fn execvp ,
.Fn execvpe ,
.Fn fexecve ,
.Fn popen ,
.Fn posix_spawn ,
.Fn posix_spawnp ,
.Fn system ,
.Xr execve 2 ,
.Xr execl 3 ,
.Xr execle 3 ,
.Xr execlp 3 ,
.Xr exect 3 ,
.Xr execv 3 ,
.Xr execveat 3 ,
.Xr execvP 3 ,
.Xr execvp 3 ,
.Xr execvpe 3 ,
.Xr fexecve 3 ,
.Xr popen 3 ,
.Xr posix_spawn 3 ,
.Xr posix_spawnp 3 ,
.Xr system 3 ,
and
.Fn wordexp
.Xr wordexp 3
library functions that prevent the execution of further commands.
This is used to implement the
.Em noexec
@ -519,9 +519,9 @@ that can log what
is doing internally if there is a problem.
.Pp
A
.Li Debug
.Em Debug
line consists of the
.Li Debug
.Em Debug
keyword, followed by the name of the program, plugin, or shared object
to debug, the debug file name, and a comma-separated list of debug flags.
The debug flag syntax used by
@ -557,25 +557,25 @@ intercept functionality on some systems.
As of
.Nm sudo
1.8.12, multiple
.Li Debug
.Em Debug
entries may be specified per program.
Older versions of
.Nm sudo
only support a single
.Li Debug
.Em Debug
entry per program.
Plugin-specific
.Li Debug
.Em Debug
entries are also supported starting with
.Nm sudo
1.8.12 and are matched by either the base name of the plugin that was loaded
(for example
.Li sudoers.so )
.Pa sudoers.so )
or by the plugin's fully-qualified path name.
Previously, the
.Nm sudoers
plugin shared the same
.Li Debug
.Em Debug
entry as the
.Nm sudo
front-end and could not be configured separately.

View File

@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.TH "SUDO" "@mansectsu@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.TH "SUDO" "@mansectsu@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
@ -41,7 +41,7 @@
.HP 5n
\fBsudo\fR
\fB\-v\fR
[\fB\-ABknS\fR]
[\fB\-ABkNnS\fR]
.if \n(BA [\fB\-a\fR\ \fItype\fR]
[\fB\-g\fR\ \fIgroup\fR]
[\fB\-h\fR\ \fIhost\fR]
@ -51,7 +51,7 @@
.HP 5n
\fBsudo\fR
\fB\-l\fR
[\fB\-ABknS\fR]
[\fB\-ABkNnS\fR]
.if \n(BA [\fB\-a\fR\ \fItype\fR]
[\fB\-g\fR\ \fIgroup\fR]
[\fB\-h\fR\ \fIhost\fR]
@ -81,7 +81,7 @@
.br
.HP 9n
\fBsudoedit\fR
[\fB\-ABknS\fR]
[\fB\-ABkNnS\fR]
.if \n(BA [\fB\-a\fR\ \fItype\fR]
[\fB\-C\fR\ \fInum\fR]
.if \n(LC [\fB\-c\fR\ \fIclass\fR]
@ -135,9 +135,7 @@ time limit.
This limit is policy-specific; the default password prompt timeout
for the
\fIsudoers\fR
security policy is
\fR@password_timeout@\fR
minutes.
security policy is @password_timeout@ minutes.
.PP
Security policies may support credential caching to allow the user
to run
@ -145,9 +143,7 @@ to run
again for a period of time without requiring authentication.
By default, the
\fIsudoers\fR
policy caches credentials on a per-terminal basis for
\fR@timeout@\fR
minutes.
policy caches credentials on a per-terminal basis for @timeout@ minutes.
See the
\fItimestamp_type\fR
and
@ -399,7 +395,7 @@ may be either a group name or a numeric group-ID
prefixed with the
\(oq#\(cq
character (e.g.,
\fR#0\fR
\(oq#0\(cq
for GID 0).
When running a command as a GID, many shells require that the
\(oq#\(cq
@ -532,6 +528,22 @@ is specified but not allowed by the policy,
\fBsudo\fR
will exit with a status value of 1.
.TP 12n
\fB\-N\fR, \fB\--no-update\fR
Do not update the user's cached credentials, even if the user successfully
authenticates.
Unlike the
\fB\-k\fR
flag, existing cached credentials are used if they are valid.
To detect when the user's cached credentials are valid (or when no
authentication is required), the following command can be used:
.RS 18n
sudo -Nnv
.RE
.RS 12n
.sp
Not all security policies support credential caching.
.RE
.TP 12n
\fB\-n\fR, \fB\--non-interactive\fR
Avoid prompting the user for input of any kind.
If a password is required for the command to run,
@ -558,7 +570,7 @@ policy:
.RS 12n
.PD 0
.TP 4n
\fR%H\fR
%H
expanded to the host name including the domain name (only if the
machine's host name is fully qualified or the
\fIfqdn\fR
@ -566,10 +578,10 @@ option is set in
sudoers(@mansectform@))
.PD
.TP 4n
\fR%h\fR
%h
expanded to the local host name without the domain name
.TP 4n
\fR%p\fR
%p
expanded to the name of the user whose password is being requested
(respects the
\fIrootpw\fR,
@ -579,16 +591,16 @@ and
flags in
sudoers(@mansectform@))
.TP 4n
\fR\&%U\fR
\&%U
expanded to the login name of the user the command will be run as
(defaults to root unless the
\fB\-u\fR
option is also specified)
.TP 4n
\fR%u\fR
%u
expanded to the invoking user's login name
.TP 4n
\fR%%\fR
%%
two consecutive
\(oq%\(cq
characters are collapsed into a single
@ -691,7 +703,7 @@ may be either a user name or a numeric user-ID
prefixed with the
\(oq#\(cq
character (e.g.,
\fR#0\fR
\(oq#0\(cq
for UID 0).
When running commands as a UID, many shells require that the
\(oq#\(cq
@ -724,9 +736,7 @@ For the
\fIsudoers\fR
plugin, this extends the
\fBsudo\fR
timeout for another
\fR@timeout@\fR
minutes by default, but does not run a command.
timeout for another @timeout@ minutes by default, but does not run a command.
Not all security policies support cached credentials.
.TP 12n
\fB\--\fR
@ -762,7 +772,7 @@ option is set in
the command to be run has the
\fRSETENV\fR
tag set or the command matched is
\fRALL\fR,
\fBALL\fR,
the user may set variables that would otherwise be forbidden.
See
sudoers(@mansectform@)
@ -970,7 +980,7 @@ run in a new pty,
may execute the command directly instead of running it as a child process.
.SS "Plugins"
Plugins may be specified via
\fRPlugin\fR
\fIPlugin\fR
directives in the
sudo.conf(@mansectform@)
file.
@ -981,7 +991,7 @@ binary.
If no
sudo.conf(@mansectform@)
file is present, or if it doesn't contain any
\fRPlugin\fR
\fIPlugin\fR
lines,
\fBsudo\fR
will use
@ -1070,9 +1080,9 @@ By default,
\fBsudo\fR
will only log the command it explicitly runs.
If a user runs a command such as
\fRsudo su\fR
\(oqsudo su\(cq
or
\fRsudo sh\fR,
\(oqsudo sh\(cq,
subsequent commands run from that shell are not subject to
\fBsudo\fR's
security policy.
@ -1160,7 +1170,7 @@ or when
is enabled in
\fIsudoers\fR
and
\fIHOME\fR
\fRHOME\fR
is not present in the
\fIenv_keep\fR
list.
@ -1210,8 +1220,7 @@ Default editor to use in
Set to the group-ID of the user who invoked sudo.
.TP 17n
\fRSUDO_PROMPT\fR
Used as the default password prompt unless
the
Used as the default password prompt unless the
\fB\-p\fR
option was specified.
.TP 17n
@ -1299,7 +1308,7 @@ $ sudo shutdown -r +15 "quick reboot"
.PP
To make a usage listing of the directories in the /home partition.
The commands are run in a sub-shell to allow the
\fRcd\fR
\(oqcd\(cq
command and file redirection to work.
.nf
.sp
@ -1484,7 +1493,7 @@ plugin's
functionality.
.PP
It is not meaningful to run the
\fRcd\fR
\(oqcd\(cq
command directly via sudo, e.g.,
.nf
.sp

View File

@ -24,7 +24,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDO @mansectsu@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -36,7 +36,7 @@
.Fl h | K | k | V
.Nm sudo
.Fl v
.Op Fl ABknS
.Op Fl ABkNnS
.if \n(BA \{\
.Op Fl a Ar type
.\}
@ -46,7 +46,7 @@
.Op Fl u Ar user
.Nm sudo
.Fl l
.Op Fl ABknS
.Op Fl ABkNnS
.if \n(BA \{\
.Op Fl a Ar type
.\}
@ -80,7 +80,7 @@
.Op Fl i | s
.Op Ar command
.Nm sudoedit
.Op Fl ABknS
.Op Fl ABkNnS
.if \n(BA \{\
.Op Fl a Ar type
.\}
@ -139,9 +139,7 @@ time limit.
This limit is policy-specific; the default password prompt timeout
for the
.Em sudoers
security policy is
.Li @password_timeout@
minutes.
security policy is @password_timeout@ minutes.
.Pp
Security policies may support credential caching to allow the user
to run
@ -149,9 +147,7 @@ to run
again for a period of time without requiring authentication.
By default, the
.Em sudoers
policy caches credentials on a per-terminal basis for
.Li @timeout@
minutes.
policy caches credentials on a per-terminal basis for @timeout@ minutes.
See the
.Em timestamp_type
and
@ -380,7 +376,7 @@ may be either a group name or a numeric group-ID
prefixed with the
.Ql #
character (e.g.,
.Li #0
.Ql #0
for GID 0).
When running a command as a GID, many shells require that the
.Ql #
@ -505,6 +501,17 @@ If a
is specified but not allowed by the policy,
.Nm
will exit with a status value of 1.
.It Fl N , -no-update
Do not update the user's cached credentials, even if the user successfully
authenticates.
Unlike the
.Fl k
flag, existing cached credentials are used if they are valid.
To detect when the user's cached credentials are valid (or when no
authentication is required), the following command can be used:
.Dl sudo -Nnv
.Pp
Not all security policies support credential caching.
.It Fl n , -non-interactive
Avoid prompting the user for input of any kind.
If a password is required for the command to run,
@ -526,15 +533,15 @@ escape sequences are supported by the
.Em sudoers
policy:
.Bl -tag -width 2n
.It Li %H
.It %H
expanded to the host name including the domain name (only if the
machine's host name is fully qualified or the
.Em fqdn
option is set in
.Xr sudoers @mansectform@ )
.It Li %h
.It %h
expanded to the local host name without the domain name
.It Li %p
.It %p
expanded to the name of the user whose password is being requested
(respects the
.Em rootpw ,
@ -543,14 +550,14 @@ and
.Em runaspw
flags in
.Xr sudoers @mansectform@ )
.It Li \&%U
.It \&%U
expanded to the login name of the user the command will be run as
(defaults to root unless the
.Fl u
option is also specified)
.It Li %u
.It %u
expanded to the invoking user's login name
.It Li %%
.It %%
two consecutive
.Ql %
characters are collapsed into a single
@ -645,7 +652,7 @@ may be either a user name or a numeric user-ID
prefixed with the
.Ql #
character (e.g.,
.Li #0
.Ql #0
for UID 0).
When running commands as a UID, many shells require that the
.Ql #
@ -676,9 +683,7 @@ For the
.Em sudoers
plugin, this extends the
.Nm
timeout for another
.Li @timeout@
minutes by default, but does not run a command.
timeout for another @timeout@ minutes by default, but does not run a command.
Not all security policies support cached credentials.
.It Fl -
The
@ -712,9 +717,9 @@ If the
option is set in
.Em sudoers ,
the command to be run has the
.Li SETENV
.Dv SETENV
tag set or the command matched is
.Li ALL ,
.Sy ALL ,
the user may set variables that would otherwise be forbidden.
See
.Xr sudoers @mansectform@
@ -911,7 +916,7 @@ run in a new pty,
may execute the command directly instead of running it as a child process.
.Ss Plugins
Plugins may be specified via
.Li Plugin
.Em Plugin
directives in the
.Xr sudo.conf @mansectform@
file.
@ -922,7 +927,7 @@ binary.
If no
.Xr sudo.conf @mansectform@
file is present, or if it doesn't contain any
.Li Plugin
.Em Plugin
lines,
.Nm
will use
@ -1011,9 +1016,9 @@ By default,
.Nm
will only log the command it explicitly runs.
If a user runs a command such as
.Li sudo su
.Ql sudo su
or
.Li sudo sh ,
.Ql sudo sh ,
subsequent commands run from that shell are not subject to
.Nm sudo Ns 's
security policy.
@ -1096,7 +1101,7 @@ or when
is enabled in
.Em sudoers
and
.Em HOME
.Ev HOME
is not present in the
.Em env_keep
list.
@ -1138,8 +1143,7 @@ Default editor to use in
.It Ev SUDO_GID
Set to the group-ID of the user who invoked sudo.
.It Ev SUDO_PROMPT
Used as the default password prompt unless
the
Used as the default password prompt unless the
.Fl p
option was specified.
.It Ev SUDO_PS1
@ -1206,7 +1210,7 @@ $ sudo shutdown -r +15 "quick reboot"
.Pp
To make a usage listing of the directories in the /home partition.
The commands are run in a sub-shell to allow the
.Li cd
.Ql cd
command and file redirection to work.
.Bd -literal -offset 4n
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
@ -1374,7 +1378,7 @@ plugin's
functionality.
.Pp
It is not meaningful to run the
.Li cd
.Ql cd
command directly via sudo, e.g.,
.Bd -literal -offset 4n
$ sudo cd /usr/local/protected

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDO_LOGSRV.PROTO" "@mansectform@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO_LOGSRV.PROTO" "@mansectform@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -93,7 +93,7 @@ message TimeSpec {
A
\fITimeSpec\fR
is the equivalent of a POSIX
\fRstruct timespec\fR,
\fIstruct timespec\fR,
containing seconds and nanoseconds members.
The
\fItv_sec\fR

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDO_LOGSRV.PROTO @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -87,7 +87,7 @@ message TimeSpec {
A
.Em TimeSpec
is the equivalent of a POSIX
.Li struct timespec ,
.Vt struct timespec ,
containing seconds and nanoseconds members.
The
.Em tv_sec
@ -237,10 +237,10 @@ If the command was terminated by a signal, this is set to the
name of the signal without the leading
.Dq SIG .
For example,
.Li INT ,
.Li TERM ,
.Li KILL ,
.Li SEGV .
.Dv INT ,
.Dv TERM ,
.Dv KILL ,
.Dv SEGV .
.It error
A message from the client indicating that the command was terminated
unexpectedly due to an error.
@ -397,9 +397,9 @@ should be calculated using a monotonic clock where possible.
The signal name without the leading
.Dq SIG .
For example,
.Li STOP ,
.Li TSTP ,
.Li CONT .
.Dv STOP ,
.Dv TSTP ,
.Dv CONT .
.El
.Sh Server Messages
A

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -168,14 +168,16 @@ will enable the TCP keepalive socket option on the client connection.
This enables the periodic transmission of keepalive messages to the client.
If the client does not respond to a message in time, the connection will
be closed.
Defaults to true.
Defaults to
\fItrue\fR.
.TP 10n
timeout = number
The amount of time, in seconds,
\fBsudo_logsrvd\fR
will wait for the client to respond.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
\fI30\fR.
.TP 10n
tls_cacert = path
The path to a certificate authority bundle file, in PEM format,
@ -202,7 +204,7 @@ authority, the
setting must be set to a CA bundle that contains the CA certificate
used to generate the client certificate.
The default value is
\fRfalse\fR.
\fIfalse\fR.
.TP 10n
tls_ciphers_v12 = string
A list of ciphers to use for connections secured by TLS version 1.2 only,
@ -214,7 +216,7 @@ section in
openssl-ciphers(1)
for full details.
The default value is
\fRHIGH:!aNULL\fR
\(lqHIGH:!aNULL\(rq
which consists of encryption cipher suites with key lengths larger than
128 bits, and some cipher suites with 128-bit keys.
Cipher suites that offer no authentication are excluded.
@ -241,7 +243,8 @@ TLS_AES_128_CCM_8_SHA256
.RE
.RS 10n
.sp
The default cipher suite is TLS_AES_256_GCM_SHA384.
The default cipher suite is
\(lqTLS_AES_256_GCM_SHA384\(rq.
.RE
.PD
.TP 10n
@ -274,7 +277,8 @@ configuration is changed.
If false, no verification is performed of the server certificate.
When using self-signed certificates without a certificate authority,
this setting should be set to false.
The default value is true.
The default value is
\fItrue\fR.
.SS "relay"
The
\fIrelay\fR
@ -301,7 +305,8 @@ setting controls the amount of time
\fBsudo_logsrvd\fR
will wait for the relay to respond.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
\fI30\fR.
.TP 10n
relay_dir = path
The directory in which log messages are temporarily stored before they
@ -339,7 +344,8 @@ lines are specified, the first available relay host will be used.
retry_interval = number
The number of seconds to wait after a connection error before making
a new attempt to forward a message to a relay host.
The default value is 30 seconds.
The default value is
\fI30\fR.
.TP 10n
store_first = boolean
If true,
@ -365,7 +371,8 @@ The amount of time, in seconds,
\fBsudo_logsrvd\fR
will wait for the relay server to respond after a connection has succeeded.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
\fI30\fR.
.TP 10n
tls_cacert = path
The path to a certificate authority bundle file, in PEM format,
@ -455,7 +462,7 @@ If set, I/O logs will be compressed using
Enabling compression can make it harder to view the logs in real-time as
the program is executing due to buffering.
The default value is
\fRfalse\fR.
\fIfalse\fR.
.TP 10n
iolog_dir = path
The top-level directory to use when constructing the path
@ -471,30 +478,30 @@ escape sequences are supported:
.RS 10n
.PD 0
.TP 6n
\fR%{seq}\fR
%{seq}
expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
where every two digits are used to form a new directory, e.g.,
\fI01/00/A5\fR
.PD
.TP 6n
\fR%{user}\fR
%{user}
expanded to the invoking user's login name
.TP 6n
\fR%{group}\fR
%{group}
expanded to the name of the invoking user's real group-ID
.TP 6n
\fR%{runas_user}\fR
%{runas_user}
expanded to the login name of the user the command will
be run as (e.g., root)
.TP 6n
\fR%{runas_group}\fR
%{runas_group}
expanded to the group name of the user the command will
be run as (e.g., wheel)
.TP 6n
\fR%{hostname}\fR
%{hostname}
expanded to the local host name without the domain name
.TP 6n
\fR%{command}\fR
%{command}
expanded to the base name of the command being run
.PP
In addition, any escape sequences supported by the system's
@ -516,7 +523,7 @@ It is possible for
\fIiolog_file\fR
to contain directory components.
The default value is
\fR%{seq}\fR.
\(lq%{seq}\(rq.
.sp
See the
\fIiolog_dir\fR
@ -526,9 +533,9 @@ escape sequences.
.sp
In addition to the escape sequences, path names that end in six or
more
\fRX\fRs
\fIX\fRs
will have the
\fRX\fRs
\fIX\fRs
replaced with a unique combination of digits and letters, similar to the
mktemp(3)
function.
@ -542,7 +549,7 @@ overwritten unless
\fIiolog_file\fR
ends in six or
more
\fRX\fRs.
\fIX\fRs.
.TP 10n
iolog_flush = boolean
If set, I/O log data is flushed to disk after each write instead of
@ -553,7 +560,7 @@ of I/O log compression.
I/O logs are always flushed before sending a commit point to the client
regardless of this setting.
The default value is
\fRtrue\fR.
\fItrue\fR.
.TP 10n
iolog_group = name
The group name to look up when setting the group-ID on new I/O log
@ -579,7 +586,7 @@ When creating I/O log directories, search (execute) bits are added
to match the read and write bits specified by
\fIiolog_mode\fR.
The default value is
\fR0600\fR.
\fI0600\fR.
.TP 10n
iolog_user = name
The user name to look up when setting the owner of new
@ -599,7 +606,7 @@ the password will still be present in the I/O log.
If
\fIlog_passwords\fR
is set to
\fRfalse\fR,
\fIfalse\fR,
\fBsudo_logsrvd\fR
will attempt to prevent passwords from being logged.
It does this by using the regular expressions in
@ -617,16 +624,16 @@ when the
option is set), only the
first character of the password will be replaced in the I/O log.
The default value is
\fRtrue\fR.
\fItrue\fR.
.TP 10n
maxseq = number
The maximum sequence number that will be substituted for the
\(lq\fR%{seq}\fR\(rq
\(lq%{seq}\(rq
escape in the I/O log file (see the
\fIiolog_dir\fR
description above for more information).
While the value substituted for
\(lq\fR%{seq}\fR\(rq
\(lq%{seq}\(rq
is in base 36,
\fImaxseq\fR
itself should be expressed in decimal.
@ -634,7 +641,8 @@ Values larger than 2176782336 (which corresponds to the
base 36 sequence number
\(lqZZZZZZ\(rq)
will be silently truncated to 2176782336.
The default value is 2176782336.
The default value is
\fI2176782336\fR.
.TP 10n
passprompt_regex = string
One or more POSIX extended regular expressions used to
@ -669,7 +677,8 @@ log_exit = boolean
If true,
\fBsudo_logsrvd\fR
will log an event when a command exits or is terminated by a signal.
Defaults to false.
Defaults to
\fIfalse\fR.
.TP 6n
log_format = string
The event log format.
@ -691,7 +700,7 @@ syslog(3).
facility = string
Syslog facility if syslog is being used for logging.
Defaults to
\fR@logfac@\fR.
\fI@logfac@\fR.
.sp
The following syslog facilities are supported:
\fBauthpriv\fR
@ -714,7 +723,7 @@ accept_priority = string
Syslog priority to use when the user is allowed to run a command and
authentication is successful.
Defaults to
\fR@goodpri@\fR.
\fI@goodpri@\fR.
.sp
The following syslog priorities are supported:
\fBalert\fR,
@ -735,7 +744,7 @@ reject_priority = string
Syslog priority to use when the user is not allowed to run a command or
when authentication is unsuccessful.
Defaults to
\fR@badpri@\fR.
\fI@badpri@\fR.
.sp
See
\fIaccept_priority\fR
@ -744,7 +753,7 @@ for the list of supported syslog priorities.
alert_priority = string
Syslog priority to use for event log alert messages received from the client.
Defaults to
\fR@badpri@\fR.
\fI@badpri@\fR.
.sp
See
\fIaccept_priority\fR
@ -779,7 +788,7 @@ server_facility = string
Syslog facility if syslog is being used for server warning messages.
See above for a list of supported facilities.
Defaults to
\fRdaemon\fR
\fIdaemon\fR
.SS "logfile"
The
\fIlogfile\fR
@ -800,10 +809,12 @@ Formatting is performed via the system's
strftime(3)
function so any escape sequences supported by that function will be expanded.
The default value is
\(lq\fR%h %e %T\fR\(rq
\(lq%h %e %T\(rq
which produces dates like
\(lqOct 3 07:15:24\(rq
in the C locale.
in the
\(oqC\(cq
locale.
.SH "FILES"
.TP 26n
\fI@sysconfdir@/sudo_logsrvd.conf\fR

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDO_LOGSRVD.CONF @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -152,13 +152,15 @@ will enable the TCP keepalive socket option on the client connection.
This enables the periodic transmission of keepalive messages to the client.
If the client does not respond to a message in time, the connection will
be closed.
Defaults to true.
Defaults to
.Em true .
.It timeout = number
The amount of time, in seconds,
.Nm sudo_logsrvd
will wait for the client to respond.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
.Em 30 .
.It tls_cacert = path
The path to a certificate authority bundle file, in PEM format,
to use instead of the system's default certificate authority database
@ -182,7 +184,7 @@ authority, the
setting must be set to a CA bundle that contains the CA certificate
used to generate the client certificate.
The default value is
.Li false .
.Em false .
.It tls_ciphers_v12 = string
A list of ciphers to use for connections secured by TLS version 1.2 only,
separated by a colon
@ -193,7 +195,7 @@ section in
.Xr openssl-ciphers 1
for full details.
The default value is
.Li HIGH:!aNULL
.Dq HIGH:!aNULL
which consists of encryption cipher suites with key lengths larger than
128 bits, and some cipher suites with 128-bit keys.
Cipher suites that offer no authentication are excluded.
@ -212,7 +214,8 @@ but should include the following:
.It TLS_AES_128_CCM_8_SHA256
.El
.Pp
The default cipher suite is TLS_AES_256_GCM_SHA384.
The default cipher suite is
.Dq TLS_AES_256_GCM_SHA384 .
.It tls_dhparams = path
The path to a file containing custom Diffie-Hellman parameters in PEM format.
This file can be created with the following command:
@ -235,7 +238,8 @@ configuration is changed.
If false, no verification is performed of the server certificate.
When using self-signed certificates without a certificate authority,
this setting should be set to false.
The default value is true.
The default value is
.Em true .
.El
.Ss relay
The
@ -263,7 +267,8 @@ setting controls the amount of time
.Nm sudo_logsrvd
will wait for the relay to respond.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
.Em 30 .
.It relay_dir = path
The directory in which log messages are temporarily stored before they
are sent to the relay host.
@ -298,7 +303,8 @@ lines are specified, the first available relay host will be used.
.It retry_interval = number
The number of seconds to wait after a connection error before making
a new attempt to forward a message to a relay host.
The default value is 30 seconds.
The default value is
.Em 30 .
.It store_first = boolean
If true,
.Nm sudo_logsrvd
@ -321,7 +327,8 @@ The amount of time, in seconds,
.Nm sudo_logsrvd
will wait for the relay server to respond after a connection has succeeded.
A value of 0 will disable the timeout.
The default value is 30.
The default value is
.Em 30 .
.It tls_cacert = path
The path to a certificate authority bundle file, in PEM format,
to use instead of the system's default certificate authority database
@ -404,7 +411,7 @@ If set, I/O logs will be compressed using
Enabling compression can make it harder to view the logs in real-time as
the program is executing due to buffering.
The default value is
.Li false .
.Em false .
.It iolog_dir = path
The top-level directory to use when constructing the path
name for the I/O log directory.
@ -416,23 +423,23 @@ The following percent
.Pq Ql %
escape sequences are supported:
.Bl -tag -width 4n
.It Li %{seq}
.It %{seq}
expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
where every two digits are used to form a new directory, e.g.,
.Pa 01/00/A5
.It Li %{user}
.It %{user}
expanded to the invoking user's login name
.It Li %{group}
.It %{group}
expanded to the name of the invoking user's real group-ID
.It Li %{runas_user}
.It %{runas_user}
expanded to the login name of the user the command will
be run as (e.g., root)
.It Li %{runas_group}
.It %{runas_group}
expanded to the group name of the user the command will
be run as (e.g., wheel)
.It Li %{hostname}
.It %{hostname}
expanded to the local host name without the domain name
.It Li %{command}
.It %{command}
expanded to the base name of the command being run
.El
.Pp
@ -453,7 +460,7 @@ It is possible for
.Em iolog_file
to contain directory components.
The default value is
.Li %{seq} .
.Dq %{seq} .
.Pp
See the
.Em iolog_dir
@ -463,9 +470,9 @@ escape sequences.
.Pp
In addition to the escape sequences, path names that end in six or
more
.Li X Ns s
.Em X Ns s
will have the
.Li X Ns s
.Em X Ns s
replaced with a unique combination of digits and letters, similar to the
.Xr mktemp 3
function.
@ -479,7 +486,7 @@ overwritten unless
.Em iolog_file
ends in six or
more
.Li X Ns s .
.Em X Ns s .
.It iolog_flush = boolean
If set, I/O log data is flushed to disk after each write instead of
buffering it.
@ -489,7 +496,7 @@ of I/O log compression.
I/O logs are always flushed before sending a commit point to the client
regardless of this setting.
The default value is
.Li true .
.Em true .
.It iolog_group = name
The group name to look up when setting the group-ID on new I/O log
files and directories.
@ -513,7 +520,7 @@ When creating I/O log directories, search (execute) bits are added
to match the read and write bits specified by
.Em iolog_mode .
The default value is
.Li 0600 .
.Em 0600 .
.It iolog_user = name
The user name to look up when setting the owner of new
I/O log files and directories.
@ -531,7 +538,7 @@ the password will still be present in the I/O log.
If
.Em log_passwords
is set to
.Li false ,
.Em false ,
.Nm sudo_logsrvd
will attempt to prevent passwords from being logged.
It does this by using the regular expressions in
@ -549,15 +556,15 @@ when the
option is set), only the
first character of the password will be replaced in the I/O log.
The default value is
.Li true .
.Em true .
.It maxseq = number
The maximum sequence number that will be substituted for the
.Dq Li %{seq}
.Dq %{seq}
escape in the I/O log file (see the
.Em iolog_dir
description above for more information).
While the value substituted for
.Dq Li %{seq}
.Dq %{seq}
is in base 36,
.Em maxseq
itself should be expressed in decimal.
@ -565,7 +572,8 @@ Values larger than 2176782336 (which corresponds to the
base 36 sequence number
.Dq ZZZZZZ )
will be silently truncated to 2176782336.
The default value is 2176782336.
The default value is
.Em 2176782336 .
.It passprompt_regex = string
One or more POSIX extended regular expressions used to
match password prompts in the terminal output when
@ -599,7 +607,8 @@ The default value is
If true,
.Nm sudo_logsrvd
will log an event when a command exits or is terminated by a signal.
Defaults to false.
Defaults to
.Em false .
.It log_format = string
The event log format.
Supported log formats are
@ -621,7 +630,7 @@ section configures how events are logged via
.It facility = string
Syslog facility if syslog is being used for logging.
Defaults to
.Li @logfac@ .
.Em @logfac@ .
.Pp
The following syslog facilities are supported:
.Sy authpriv
@ -643,7 +652,7 @@ and
Syslog priority to use when the user is allowed to run a command and
authentication is successful.
Defaults to
.Li @goodpri@ .
.Em @goodpri@ .
.Pp
The following syslog priorities are supported:
.Sy alert ,
@ -663,7 +672,7 @@ will disable logging of successful commands.
Syslog priority to use when the user is not allowed to run a command or
when authentication is unsuccessful.
Defaults to
.Li @badpri@ .
.Em @badpri@ .
.Pp
See
.Em accept_priority
@ -671,7 +680,7 @@ for the list of supported syslog priorities.
.It alert_priority = string
Syslog priority to use for event log alert messages received from the client.
Defaults to
.Li @badpri@ .
.Em @badpri@ .
.Pp
See
.Em accept_priority
@ -704,7 +713,7 @@ JSON-format log entries are never split and are not affected by
Syslog facility if syslog is being used for server warning messages.
See above for a list of supported facilities.
Defaults to
.Li daemon
.Em daemon
.El
.Ss logfile
The
@ -725,10 +734,12 @@ Formatting is performed via the system's
.Xr strftime 3
function so any escape sequences supported by that function will be expanded.
The default value is
.Dq Li "%h %e %T"
.Dq "%h %e %T"
which produces dates like
.Dq Oct 3 07:15:24
in the C locale.
in the
.Ql C
locale.
.El
.Sh FILES
.Bl -tag -width 24n

View File

@ -117,7 +117,7 @@ section.
.SS "Debugging sudo_logsrvd"
\fBsudo_logsrvd\fR
supports a flexible debugging framework that is configured via
\fRDebug\fR
\fIDebug\fR
lines in the
sudo.conf(@mansectform@)
file.

View File

@ -112,7 +112,7 @@ section.
.Ss Debugging sudo_logsrvd
.Nm
supports a flexible debugging framework that is configured via
.Li Debug
.Em Debug
lines in the
.Xr sudo.conf @mansectform@
file.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDO_PLUGIN_PYTHON" "5" "June 6, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO_PLUGIN_PYTHON" "5" "September 11, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -96,9 +96,9 @@ When the plugin loads,
will create an instance of this class and call the methods.
The actual methods required depent on the type of the plugin,
but most return an
\(lqint\(rq
\fIint\fR
result code, as documented in
sudo_plugin(@mansectsu@),
sudo_plugin(@mansectform@),
that indicates whether or not the method was successful.
The Python sudo module defines the following constants to improve readability:
.RS 4n
@ -120,12 +120,12 @@ l l.
.RE
.PP
If a function returns
\fINone\fR
\fRNone\fR
(for example, if it does not call return),
it will be considered to have returned
\fRsudo.RC.OK\fR.
If an exception is raised (other than sudo.PluginException), the backtrace will be
shown to the user and the plugin function will return
If an exception is raised (other than sudo.PluginException), the
backtrace will be shown to the user and the plugin function will return
\fRsudo.RC.ERROR\fR.
If that is not acceptable, you must catch the exception and handle it yourself.
.PP
@ -151,7 +151,7 @@ Running the Python interpreter and bridging between C and Python is
handled by the
\fBsudo\fR
plugin
\fRpython_plugin.so\fR.
\fIpython_plugin.so\fR.
This shared object can be loaded like any other dynamic
\fBsudo\fR
plugin and should receive the path and the class name of the Python
@ -219,7 +219,7 @@ sudo.conf(@mansectform@).
.PP
A policy plugin may have the following member functions:
.TP 6n
\fBconstructor\fR
\fIconstructor\fR
.nf
.RS 6n
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
@ -235,7 +235,9 @@ as member variables in the object.
.sp
The constructor matches the
\fBopen\fR()
function in the C sudo plugin API.
function in the C
\fBsudo\fR
plugin API.
.sp
The function arguments are as follows:
.TP 6n
@ -279,7 +281,7 @@ documentation in
sudo_plugin(@mansectform@).
.RE
.TP 6n
\fBcheck_policy\fR
\fIcheck_policy\fR
.nf
.RS 6n
check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
@ -367,7 +369,7 @@ format.
.RE
.PD
.TP 6n
\fBinit_session\fR
\fIinit_session\fR
.nf
.RS 6n
init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
@ -387,8 +389,9 @@ The function arguments are as follows:
.TP 6n
\fIuser_pwd\fR
A tuple describing the user's passwd entry.
Convertible to pwd.struct_passwd or
\fINone\fR
Convertible to
\fIpwd.struct_passwd or\fR
\fRNone\fR
if the user is not present in the password database.
.sp
Example conversion:
@ -437,7 +440,7 @@ If this is omitted, no changes will be made to
.RE
.PD
.TP 6n
\fBlist\fR
\fIlist\fR
.nf
.RS 6n
list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
@ -451,7 +454,7 @@ The function arguments are as follows:
.TP 6n
\fIargv\fR
If not set to
\fINone\fR,
\fRNone\fR,
an argument vector describing a command the user wishes to check
against the policy.
.TP 6n
@ -461,14 +464,14 @@ Flag indicating whether to list in verbose mode or not.
\fIuser\fR
The name of a different user to list privileges for if the policy allows it.
If
\fINone\fR,
\fRNone\fR,
the plugin should list the privileges of the invoking user.
.PD 0
.PP
.RE
.PD
.TP 6n
\fBvalidate\fR
\fIvalidate\fR
.nf
.RS 6n
validate(self)
@ -479,7 +482,7 @@ validate(self)
For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
.RE
.TP 6n
\fBinvalidate\fR
\fIinvalidate\fR
.nf
.RS 6n
invalidate(self, remove: int)
@ -499,7 +502,7 @@ invalidating them.
.RE
.PD
.TP 6n
\fBshow_version\fR
\fIshow_version\fR
.nf
.RS 6n
show_version(self, is_verbose: int)
@ -524,7 +527,7 @@ is run as the root user.
.RE
.PD
.TP 6n
\fBclose\fR
\fIclose\fR
.br
.nf
.RS 6n
@ -537,7 +540,9 @@ Called when a command finishes executing.
.sp
Works the same as the
\fBclose\fR()
function in the C sudo plugin API, except that it only gets called if
function in the C
\fBsudo\fR
plugin API, except that it only gets called if
\fBsudo\fR
attempts to execute the command.
.sp
@ -569,8 +574,10 @@ Plugin python_policy python_plugin.so \e
.RE
.fi
.PP
Be aware, however, that you cannot enable the Python policy plugin
in addition to another policy plugin, such as
Only one policy plugin can be enabled at a time so you must disable
any other policy plugin listed in
\fI@sysconfdir@/sudo.conf\fR,
such as
sudoers(@mansectform@).
.SS "I/O plugin API"
I/O plugins must be registered in
@ -588,7 +595,7 @@ Currently only 8 python I/O plugins can be loaded at once.
.PP
An I/O plugin may have the following member functions:
.TP 6n
\fBconstructor\fR
\fIconstructor\fR
.nf
.RS 6n
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
@ -604,7 +611,9 @@ as member variables in the object.
.sp
The constructor matches the
\fBopen\fR()
function in the C sudo plugin API.
function in the C
\fBsudo\fR
plugin API.
.sp
The function arguments are as follows:
.TP 6n
@ -648,7 +657,7 @@ documentation in
sudo_plugin(@mansectform@).
.RE
.TP 6n
\fBopen\fR
\fIopen\fR
.nf
.RS 6n
open(self, argv: Tuple[str, ...],
@ -661,13 +670,15 @@ Receives the command the user wishes to run.
.sp
Works the same as the
\fBopen\fR()
function in the C sudo plugin API except that:
function in the C
\fBsudo\fR
plugin API except that:
.sp
.RS 10n
.PD 0
.TP 3n
\fB\(bu\fR
It only gets called before the user would execute some command
It only gets called when there is a command to be executed
(and not for a version query for example).
.TP 3n
\fB\(bu\fR
@ -708,7 +719,7 @@ If the function returns
no I/O will be sent to the plugin.
.RE
.TP 6n
\fBlog_ttyin\fR, \fBlog_ttyout\fR, \fBlog_stdin\fR, \fBlog_stdout\fR, \fBlog_stderr\fR
\fIlog_ttyin\fR, \fIlog_ttyout\fR, \fIlog_stdin\fR, \fIlog_stdout\fR, \fIlog_stderr\fR
.nf
.RS 6n
log_ttyin(self, buf: str) -> int
@ -736,8 +747,8 @@ constants.
.sp
If
\fRsudo.RC.ERROR\fR
is returned, the running command will be terminated and all of the plugin's logging
functions will be disabled.
is returned, the running command will be terminated and all of the
plugin's logging functions will be disabled.
Other I/O logging plugins will still receive any remaining
input or output that has not yet been processed.
.sp
@ -751,7 +762,7 @@ the command will be terminated and the data will not be written to the
terminal, though it will still be sent to any other I/O logging plugins.
.RE
.TP 6n
\fBchange_winsize\fR
\fIchange_winsize\fR
.nf
.RS 6n
change_winsize(self, line: int, cols: int) -> int
@ -772,7 +783,7 @@ The number of columns of the terminal.
.RE
.PD
.TP 6n
\fBlog_suspend\fR
\fIlog_suspend\fR
.nf
.RS 6n
log_suspend(self, signo: int) -> int
@ -793,7 +804,7 @@ if the command was resumed.
.RE
.PD
.TP 6n
\fBshow_version\fR
\fIshow_version\fR
.nf
.RS 6n
show_version(self, is_verbose: int)
@ -817,7 +828,7 @@ is run as the root user.
.RE
.PD
.TP 6n
\fBclose\fR
\fIclose\fR
.br
.nf
.RS 6n
@ -825,11 +836,13 @@ close(self, exit_status: int, error: int) -> None
.RE
.fi
.RS 6n
Called when a command execution finished.
Called when a command finishes execution.
.sp
Works the same as the
\fBclose\fR()
function in the C sudo plugin API, except that it only gets called if
function in the C
\fBsudo\fR
plugin API, except that it only gets called if
\fBsudo\fR
attempts to execute the command.
.sp
@ -849,7 +862,7 @@ system call, otherwise 0.
.RE
.PD
.SS "I/O plugin example"
Sudo ships a Python I/O plugin example.
Sudo ships with a Python I/O plugin example.
To try it, register it by adding the following lines to
\fI@sysconfdir@/sudo.conf\fR:
.nf
@ -874,9 +887,9 @@ Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
Sudo supports loading multiple audit plugins.
Currently only 8 python audit plugins can be loaded at once.
.PP
An audit plugin may have the following member functions (all of them are optional):
An audit plugin may have the following member functions (all of which are optional):
.TP 6n
\fBconstructor\fR
\fIconstructor\fR
.nf
.RS 6n
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
@ -890,7 +903,9 @@ as member variables in the object.
.sp
The constructor matches the
\fBopen\fR()
function in the C sudo plugin API.
function in the C
\fBsudo\fR
plugin API.
.sp
The function arguments are as follows:
.TP 6n
@ -926,7 +941,7 @@ format.
.RE
.PD
.TP 6n
\fBopen\fR
\fIopen\fR
.nf
.RS 6n
open(self, submit_optind: int,
@ -949,7 +964,7 @@ The argument vector sudo was invoked with, including all command line options.
.RE
.PD
.TP 6n
\fBclose\fR
\fIclose\fR
.br
.nf
.RS 6n
@ -964,7 +979,9 @@ The function arguments are as follows:
.TP 6n
\fIstatus_type\fR
The type of status being passed.
One of the sudo.EXIT_REASON.* constants.
One of the
\fRsudo.EXIT_REASON.*\fR
constants.
.TP 6n
\fIstatus\fR
Depending on the value of
@ -973,11 +990,11 @@ this value is either
ignored, the command's exit status as returned by the
wait(2)
system call, the value of
\fRerrno\fR
\fIerrno\fR
set by the
execve(2)
system call, or the value of
\fRerrno\fR
\fIerrno\fR
resulting from an error in the
\fBsudo\fR
front-end.
@ -986,7 +1003,7 @@ front-end.
.RE
.PD
.TP 6n
\fBshow_version\fR
\fIshow_version\fR
.nf
.RS 6n
show_version(self, is_verbose: int) -> int
@ -1011,7 +1028,7 @@ is run as the root user.
.RE
.PD
.TP 6n
\fBaccept\fR
\fIaccept\fR
.nf
.RS 6n
accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
@ -1075,7 +1092,7 @@ The environment the command will be run with.
.RE
.PD
.TP 6n
\fBreject\fR
\fIreject\fR
.nf
.RS 6n
reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
@ -1109,7 +1126,7 @@ front-end.
audit_msg
An optional string describing the reason the command was rejected by the plugin.
If the plugin did not provide a reason, audit_msg will be
\fINone\fR
\fRNone\fR.
.TP 6n
command_info
A vector of information describing the rejected command.
@ -1121,7 +1138,7 @@ manual for possible values.
.RE
.PD
.TP 6n
\fBerror\fR
\fIerror\fR
.br
.nf
.RS 6n
@ -1153,7 +1170,7 @@ front-end.
audit_msg
An optional string describing the plugin error.
If the plugin did not provide a description, it will be
\fINone\fR
\fRNone\fR.
.TP 6n
command_info
A vector of information describing the command.
@ -1165,7 +1182,7 @@ manual for possible values.
.RE
.PD
.SS "Audit plugin example"
Sudo ships a Python Audit plugin example.
Sudo ships with a Python Audit plugin example.
To try it, register it by adding the following lines to
\fI@sysconfdir@/sudo.conf\fR:
.nf
@ -1194,7 +1211,7 @@ Currently only 8 python approval plugins can be loaded at once.
.PP
An approval plugin may have the following member functions:
.TP 6n
\fBconstructor\fR
\fIconstructor\fR
.nf
.RS 6n
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
@ -1210,7 +1227,9 @@ as member variables in the object.
.sp
The constructor matches the
\fBopen\fR()
function in the C sudo plugin API.
function in the C
\fBsudo\fR
plugin API.
.sp
The function arguments are as follows:
.TP 6n
@ -1254,7 +1273,7 @@ The argument vector sudo was invoked with, including all command line options.
.RE
.PD
.TP 6n
\fBshow_version\fR
\fIshow_version\fR
.nf
.RS 6n
show_version(self, is_verbose: int) -> int
@ -1262,10 +1281,11 @@ show_version(self, is_verbose: int) -> int
.fi
.RS 6n
.sp
Display the version. (Same as for all the other plugins.)
Display the version.
(Same as for all the other plugins.)
.RE
.TP 6n
\fBcheck\fR
\fIcheck\fR
.br
.nf
.RS 6n
@ -1306,7 +1326,7 @@ The environment the command will be run with.
.RE
.PD
.SS "Approval plugin example"
Sudo ships a Python Approval plugin example.
Sudo ships with a Python Approval plugin example.
To try it, register it by adding the following lines to
\fI@sysconfdir@/sudo.conf\fR:
.nf
@ -1337,7 +1357,7 @@ Currently, only a single group plugin can be registered in
.PP
A group provider plugin may have the following member functions:
.TP 6n
\fBconstructor\fR
\fIconstructor\fR
.nf
.RS 6n
__init__(self, args: Tuple[str, ...], version: str)
@ -1366,7 +1386,7 @@ The version of the Python Group Plugin API.
.RE
.PD
.TP 6n
\fBquery\fR
\fIquery\fR
.br
.nf
.RS 6n
@ -1402,7 +1422,7 @@ is not present in the password database,
will be
\fRNULL\fR.
.SS "Group plugin example"
Sudo ships a Python group plugin example.
Sudo ships with a Python group plugin example.
To try it, register it in the
\fIsudoers\fR
file by adding the following lines:
@ -1419,7 +1439,7 @@ The example plugin will tell
\fBsudo\fR
that the user
\fItest\fR
is part of the non-unix group
is part of the non-Unix group
\fImygroup\fR.
If you add a rule that uses this group, it will affect the
\fItest\fR
@ -1444,16 +1464,18 @@ written in Python.
A Python plugin can interact with the user using the
\fBsudo.conv\fR()
function which displays one or more messages described by the
\fBsudo.ConvMessage\fR
\fRsudo.ConvMessage\fR
class.
This is the Python equivalent of the
\fBconversation\fR()
function in the C sudo plugin API.
function in the C
\fBsudo\fR
plugin API.
A plugin should not attempt to read directly from the standard input or
the user's tty (neither of which are guaranteed to exist).
.PP
The
\fBsudo.ConvMessage\fR
\fRsudo.ConvMessage\fR
class specifies how the user interaction should occur:
.nf
.sp
@ -1462,7 +1484,7 @@ sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
.RE
.fi
.PP
\fBsudo.ConvMessage\fR
\fRsudo.ConvMessage\fR
member variables:
.TP 6n
\fImsg_type\fR
@ -1474,7 +1496,7 @@ constants below.
\fImsg\fR
The message to display to the user.
The caller must include a trailing newline in
\fRmsg\fR
\fImsg\fR
if one is to be displayed.
.TP 6n
\fItimeout\fR
@ -1493,25 +1515,25 @@ To specify the message type, the following constants are available:
.PD 0
.TP 3n
\fB\(bu\fR
sudo.CONV.PROMPT_ECHO_OFF
\fRsudo.CONV.PROMPT_ECHO_OFF\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.PROMPT_ECHO_ON
\fRsudo.CONV.PROMPT_ECHO_ON\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.ERROR_MSG
\fRsudo.CONV.ERROR_MSG\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.INFO_MSG
\fRsudo.CONV.INFO_MSG\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.PROMPT_MASK
\fRsudo.CONV.PROMPT_MASK\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.PROMPT_ECHO_OK
\fRsudo.CONV.PROMPT_ECHO_OK\fR
.TP 3n
\fB\(bu\fR
sudo.CONV.PREFER_TTY
\fRsudo.CONV.PREFER_TTY\fR
.RE
.PD
.PP
@ -1534,7 +1556,7 @@ The function arguments are as follows:
.TP 6n
\fImessage(s)\fR
One of more messages (of type
\fBsudo.ConvMessage\fR),
\fRsudo.ConvMessage\fR),
each describing a conversation.
At least one message is required.
.TP 6n
@ -1554,11 +1576,11 @@ The
\fBsudo.conv\fR()
function can raise the following exceptions:
.TP 6n
\fBsudo.SudoException\fR
\fRsudo.SudoException\fR
If the conversation fails, for example when the conversation function is not
available.
.TP 6n
\fBsudo.ConversationInterrupted\fR
\fRsudo.ConversationInterrupted\fR
If the conversation function returns an error, e.g., the timeout passed
or the user interrupted the conversation by pressing control-C.
.SS "Conversation example"
@ -1618,7 +1640,7 @@ debug system.
\fIEnabling debugging in sudo.conf\fR
.PP
To enable debug messages, add a
\fRDebug\fR
\fIDebug\fR
line to
sudo.conf(@mansectform@)
with the program set to
@ -1710,21 +1732,21 @@ l l l.
.PP
\fBsudo.conf name\fR \fBPython constant\fR \fBdescription\fR
.PP
crit sudo.DEBUG.CRIT only critical messages
crit \fRsudo.DEBUG.CRIT\fR only critical messages
.PP
err sudo.DEBUG.ERROR
err \fRsudo.DEBUG.ERROR\fR
.PP
warn sudo.DEBUG.WARN
warn \fRsudo.DEBUG.WARN\fR
.PP
notice sudo.DEBUG.NOTICE
notice \fRsudo.DEBUG.NOTICE\fR
.PP
diag sudo.DEBUG.DIAG
diag \fRsudo.DEBUG.DIAG\fR
.PP
info sudo.DEBUG.INFO
info \fRsudo.DEBUG.INFO\fR
.PP
trace sudo.DEBUG.TRACE
trace \fRsudo.DEBUG.TRACE\fR
.PP
debug sudo.DEBUG.DEBUG very extreme verbose debugging
debug \fRsudo.DEBUG.DEBUG\fR very extreme verbose debugging
.TE
.PP
\fIUsing the logging module\fR
@ -1737,11 +1759,11 @@ The log handler of sudo will map each Python log level of a message to
the appropriate sudo debug level.
The sudo debug system will only receive messages that are not filtered
out by the Python loggers.
For example, the log level of the python logger will be an additional filter
for the log messages, and is usually very different from what level is set in sudo.conf
for the sudo debug system.
For example, the log level of the python logger will be an additional
filter for the log messages, and is usually very different from
what level is set in sudo.conf for the sudo debug system.
.SS "Debug example"
Sudo ships an example debug plugin by default.
Sudo ships with an example debug plugin.
To try it, register it by adding the following lines to
\fI@sysconfdir@/sudo.conf\fR:
.nf
@ -1816,12 +1838,13 @@ This is how the plugin API accepts options and settings.
.SH "PLUGIN API CHANGELOG (Python)"
None yet
.SH "LIMITATIONS"
Only a maximum number of 8 python I/O plugins can be loaded at once.
A maximum of 8 python I/O plugins can be loaded at once.
If
\fI@sysconfdir@/sudo.conf\fR
contains more, those will be rejected with a warning message.
.PP
The Event API and the hook function API is currently not accessible for Python plugins.
The Event API and the hook function API is currently not accessible
for Python plugins.
.SH "SEE ALSO"
sudo.conf(@mansectform@),
sudo_plugin(@mansectform@),
@ -1849,7 +1872,7 @@ If you believe you have found a bug in
you can submit a bug report at https://bugzilla.sudo.ws/
.SH "SECURITY CONSIDERATIONS"
All Python plugin handling is implemented inside the
\fRpython_plugin.so\fR
\fIpython_plugin.so\fR
dynamic plugin.
Therefore, if no Python plugin is registered in
sudo.conf(@mansectform@)
@ -1875,7 +1898,7 @@ accidentally importing such file would make it possible for any user
However, during development of a plugin this might not be very convenient.
The
sudo.conf(@mansectform@)
\fRdeveloper_mode\fR
\fIdeveloper_mode\fR
option can be used to disable it.
For example:
.RS 6n

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd June 6, 2022
.Dd September 11, 2022
.Dt SUDO_PLUGIN_PYTHON @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -85,9 +85,9 @@ When the plugin loads,
will create an instance of this class and call the methods.
The actual methods required depent on the type of the plugin,
but most return an
.Dq int
.Vt int
result code, as documented in
.Xr sudo_plugin @mansectsu@ ,
.Xr sudo_plugin @mansectform@ ,
that indicates whether or not the method was successful.
The Python sudo module defines the following constants to improve readability:
.Bl -column "sudo.RC.USAGE_ERROR" "XXX" -offset 4n
@ -100,12 +100,12 @@ The Python sudo module defines the following constants to improve readability:
.El
.Pp
If a function returns
.Em None
.Dv None
(for example, if it does not call return),
it will be considered to have returned
.Dv sudo.RC.OK .
If an exception is raised (other than sudo.PluginException), the backtrace will be
shown to the user and the plugin function will return
If an exception is raised (other than sudo.PluginException), the
backtrace will be shown to the user and the plugin function will return
.Dv sudo.RC.ERROR .
If that is not acceptable, you must catch the exception and handle it yourself.
.Pp
@ -128,7 +128,7 @@ Running the Python interpreter and bridging between C and Python is
handled by the
.Nm sudo
plugin
.Li python_plugin.so .
.Pa python_plugin.so .
This shared object can be loaded like any other dynamic
.Nm sudo
plugin and should receive the path and the class name of the Python
@ -187,8 +187,8 @@ Currently, only a single policy plugin may be specified in
.Pp
A policy plugin may have the following member functions:
.Bl -tag -width 4n
.It Sy constructor
.Bd -literal
.It Fa constructor
.Bd -literal -compact
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
version: str, user_info: Tuple[str, ...],
plugin_options: Tuple[str, ...])
@ -200,7 +200,9 @@ as member variables in the object.
.Pp
The constructor matches the
.Fn open
function in the C sudo plugin API.
function in the C
.Nm sudo
plugin API.
.Pp
The function arguments are as follows:
.Bl -tag -width 4n
@ -239,7 +241,7 @@ see the policy plugin
.Fn open
documentation in
.Xr sudo_plugin @mansectform@ .
.It Sy check_policy
.It Fa check_policy
.Bd -literal -compact
check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
.Ed
@ -314,7 +316,7 @@ tuple of strings in
.Dq key=value
format.
.El
.It Sy init_session
.It Fa init_session
.Bd -literal -compact
init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
.Ed
@ -331,8 +333,9 @@ The function arguments are as follows:
.Bl -tag -width 4n
.It Fa user_pwd
A tuple describing the user's passwd entry.
Convertible to pwd.struct_passwd or
.Em None
Convertible to
.Vt pwd.struct_passwd or
.Dv None
if the user is not present in the password database.
.Pp
Example conversion:
@ -371,7 +374,7 @@ environment in
If this is omitted, no changes will be made to
.Fa user_env .
.El
.It Sy list
.It Fa list
.Bd -literal -compact
list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
.Ed
@ -382,7 +385,7 @@ The function arguments are as follows:
.Bl -tag -width 4n
.It Fa argv
If not set to
.Em None ,
.Dv None ,
an argument vector describing a command the user wishes to check
against the policy.
.It Fa is_verbose
@ -390,16 +393,16 @@ Flag indicating whether to list in verbose mode or not.
.It Fa user
The name of a different user to list privileges for if the policy allows it.
If
.Em None ,
.Dv None ,
the plugin should list the privileges of the invoking user.
.El
.It Sy validate
.It Fa validate
.Bd -literal -compact
validate(self)
.Ed
.Pp
For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
.It Sy invalidate
.It Fa invalidate
.Bd -literal -compact
invalidate(self, remove: int)
.Ed
@ -412,7 +415,7 @@ The function arguments are as follows:
If this flag is set, the plugin may remove the credentials instead of simply
invalidating them.
.El
.It Sy show_version
.It Fa show_version
.Bd -literal -compact
show_version(self, is_verbose: int)
.Ed
@ -430,7 +433,7 @@ Currently this is 1 if
.Ql sudo -V
is run as the root user.
.El
.It Sy close
.It Fa close
.Bd -literal -compact
close(self, exit_status: int, error: int)
.Ed
@ -439,7 +442,9 @@ Called when a command finishes executing.
.Pp
Works the same as the
.Fn close
function in the C sudo plugin API, except that it only gets called if
function in the C
.Nm sudo
plugin API, except that it only gets called if
.Nm sudo
attempts to execute the command.
.Pp
@ -464,8 +469,10 @@ Plugin python_policy python_plugin.so \e
ClassName=SudoPolicyPlugin
.Ed
.Pp
Be aware, however, that you cannot enable the Python policy plugin
in addition to another policy plugin, such as
Only one policy plugin can be enabled at a time so you must disable
any other policy plugin listed in
.Pa @sysconfdir@/sudo.conf ,
such as
.Xr sudoers @mansectform@ .
.Ss I/O plugin API
I/O plugins must be registered in
@ -480,7 +487,7 @@ Currently only 8 python I/O plugins can be loaded at once.
.Pp
An I/O plugin may have the following member functions:
.Bl -tag -width 4n
.It Sy constructor
.It Fa constructor
.Bd -literal -compact
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
version: str, user_info: Tuple[str, ...],
@ -493,7 +500,9 @@ as member variables in the object.
.Pp
The constructor matches the
.Fn open
function in the C sudo plugin API.
function in the C
.Nm sudo
plugin API.
.Pp
The function arguments are as follows:
.Bl -tag -width 4n
@ -532,7 +541,7 @@ see the I/O plugin
.Fn open
documentation in
.Xr sudo_plugin @mansectform@ .
.It Sy open
.It Fa open
.Bd -literal -compact
open(self, argv: Tuple[str, ...],
command_info: Tuple[str, ...]) -> int
@ -542,11 +551,13 @@ Receives the command the user wishes to run.
.Pp
Works the same as the
.Fn open
function in the C sudo plugin API except that:
function in the C
.Nm sudo
plugin API except that:
.Pp
.Bl -bullet -compact -offset 4n -width 1n
.It
It only gets called before the user would execute some command
It only gets called when there is a command to be executed
(and not for a version query for example).
.It
Other arguments of the C API
@ -583,7 +594,7 @@ constants.
If the function returns
.Dv sudo.RC.REJECT ,
no I/O will be sent to the plugin.
.It Sy log_ttyin , log_ttyout , log_stdin , log_stdout , log_stderr
.It Fa log_ttyin , log_ttyout , log_stdin , log_stdout , log_stderr
.Bd -literal -compact
log_ttyin(self, buf: str) -> int
log_ttyout(self, buf: str) -> int
@ -609,8 +620,8 @@ constants.
.Pp
If
.Dv sudo.RC.ERROR
is returned, the running command will be terminated and all of the plugin's logging
functions will be disabled.
is returned, the running command will be terminated and all of the
plugin's logging functions will be disabled.
Other I/O logging plugins will still receive any remaining
input or output that has not yet been processed.
.Pp
@ -622,7 +633,7 @@ If an output logging function rejects the data by returning
.Dv sudo.RC.REJECT ,
the command will be terminated and the data will not be written to the
terminal, though it will still be sent to any other I/O logging plugins.
.It Sy change_winsize
.It Fa change_winsize
.Bd -literal -compact
change_winsize(self, line: int, cols: int) -> int
.Ed
@ -635,7 +646,7 @@ The number of lines of the terminal.
.It Fa cols
The number of columns of the terminal.
.El
.It Sy log_suspend
.It Fa log_suspend
.Bd -literal -compact
log_suspend(self, signo: int) -> int
.Ed
@ -648,7 +659,7 @@ The number of the signal that caused the command to be suspended or
.Dv SIGCONT
if the command was resumed.
.El
.It Sy show_version
.It Fa show_version
.Bd -literal -compact
show_version(self, is_verbose: int)
.Ed
@ -665,15 +676,17 @@ Currently this is 1 if
.Ql sudo -V
is run as the root user.
.El
.It Sy close
.It Fa close
.Bd -literal -compact
close(self, exit_status: int, error: int) -> None
.Ed
Called when a command execution finished.
Called when a command finishes execution.
.Pp
Works the same as the
.Fn close
function in the C sudo plugin API, except that it only gets called if
function in the C
.Nm sudo
plugin API, except that it only gets called if
.Nm sudo
attempts to execute the command.
.Pp
@ -689,7 +702,7 @@ system call, otherwise 0.
.El
.El
.Ss I/O plugin example
Sudo ships a Python I/O plugin example.
Sudo ships with a Python I/O plugin example.
To try it, register it by adding the following lines to
.Pa @sysconfdir@/sudo.conf :
.Bd -literal -offset 4n
@ -708,9 +721,9 @@ Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
Sudo supports loading multiple audit plugins.
Currently only 8 python audit plugins can be loaded at once.
.Pp
An audit plugin may have the following member functions (all of them are optional):
An audit plugin may have the following member functions (all of which are optional):
.Bl -tag -width 4n
.It Sy constructor
.It Fa constructor
.Bd -literal -compact
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
@ -721,7 +734,9 @@ as member variables in the object.
.Pp
The constructor matches the
.Fn open
function in the C sudo plugin API.
function in the C
.Nm sudo
plugin API.
.Pp
The function arguments are as follows:
.Bl -tag -width 4n
@ -749,7 +764,7 @@ This is a tuple of strings, usually (but not necessarily) in
.Dq key=value
format.
.El
.It Sy open
.It Fa open
.Bd -literal -compact
open(self, submit_optind: int,
submit_argv: Tuple[str, ...]) -> int
@ -764,7 +779,7 @@ that corresponds to the first entry that is not a command line option.
.It Fa submit_argv
The argument vector sudo was invoked with, including all command line options.
.El
.It Sy close
.It Fa close
.Bd -literal -compact
close(self, status_type: int, status: int) -> None
.Ed
@ -775,7 +790,9 @@ The function arguments are as follows:
.Bl -tag -width 4n
.It Fa status_type
The type of status being passed.
One of the sudo.EXIT_REASON.* constants.
One of the
.Dv sudo.EXIT_REASON.*
constants.
.It Fa status
Depending on the value of
.Fa status_type ,
@ -783,16 +800,16 @@ this value is either
ignored, the command's exit status as returned by the
.Xr wait 2
system call, the value of
.Li errno
.Va errno
set by the
.Xr execve 2
system call, or the value of
.Li errno
.Va errno
resulting from an error in the
.Nm sudo
front-end.
.El
.It Sy show_version
.It Fa show_version
.Bd -literal -compact
show_version(self, is_verbose: int) -> int
.Ed
@ -810,7 +827,7 @@ Currently this is 1 if
.Ql sudo -V
is run as the root user.
.El
.It Sy accept
.It Fa accept
.Bd -literal -compact
accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
@ -863,7 +880,7 @@ Argument vector describing a command that will be run.
.It run_envp
The environment the command will be run with.
.El
.It Sy reject
.It Fa reject
.Bd -literal -compact
reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
command_info: Tuple[str, ...]) -> int
@ -892,15 +909,14 @@ front-end.
.It audit_msg
An optional string describing the reason the command was rejected by the plugin.
If the plugin did not provide a reason, audit_msg will be
.Em None
.
.Dv None .
.It command_info
A vector of information describing the rejected command.
See the
.Xr sudo_plugin @mansectform@
manual for possible values.
.El
.It Sy error
.It Fa error
.Bd -literal -compact
error(self, plugin_name: str, plugin_type: int, audit_msg: str,
command_info: Tuple[str, ...]) -> int
@ -926,8 +942,7 @@ front-end.
.It audit_msg
An optional string describing the plugin error.
If the plugin did not provide a description, it will be
.Em None
.
.Dv None .
.It command_info
A vector of information describing the command.
See the
@ -936,7 +951,7 @@ manual for possible values.
.El
.El
.Ss Audit plugin example
Sudo ships a Python Audit plugin example.
Sudo ships with a Python Audit plugin example.
To try it, register it by adding the following lines to
.Pa @sysconfdir@/sudo.conf :
.Bd -literal -offset 4n
@ -959,7 +974,7 @@ Currently only 8 python approval plugins can be loaded at once.
.Pp
An approval plugin may have the following member functions:
.Bl -tag -width 4n
.It Sy constructor
.It Fa constructor
.Bd -literal -compact
__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
@ -972,7 +987,9 @@ as member variables in the object.
.Pp
The constructor matches the
.Fn open
function in the C sudo plugin API.
function in the C
.Nm sudo
plugin API.
.Pp
The function arguments are as follows:
.Bl -tag -width 4n
@ -1006,13 +1023,14 @@ that corresponds to the first entry that is not a command line option.
.It Fa submit_argv
The argument vector sudo was invoked with, including all command line options.
.El
.It Sy show_version
.It Fa show_version
.Bd -literal -compact
show_version(self, is_verbose: int) -> int
.Ed
.Pp
Display the version. (Same as for all the other plugins.)
.It Sy check
Display the version.
(Same as for all the other plugins.)
.It Fa check
.Bd -literal -compact
check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
run_env: Tuple[str, ...]) -> int
@ -1042,7 +1060,7 @@ The environment the command will be run with.
.El
.El
.Ss Approval plugin example
Sudo ships a Python Approval plugin example.
Sudo ships with a Python Approval plugin example.
To try it, register it by adding the following lines to
.Pa @sysconfdir@/sudo.conf :
.Bd -literal -offset 4n
@ -1067,7 +1085,7 @@ Currently, only a single group plugin can be registered in
.Pp
A group provider plugin may have the following member functions:
.Bl -tag -width 4n
.It Sy constructor
.It Fa constructor
.Bd -literal -compact
__init__(self, args: Tuple[str, ...], version: str)
.Ed
@ -1088,7 +1106,7 @@ format).
.It Fa version
The version of the Python Group Plugin API.
.El
.It Sy query
.It Fa query
.Bd -literal -compact
query(self, user: str, group: str, user_pwd: Tuple)
.Ed
@ -1118,7 +1136,7 @@ will be
.Dv NULL .
.El
.Ss Group plugin example
Sudo ships a Python group plugin example.
Sudo ships with a Python group plugin example.
To try it, register it in the
.Em sudoers
file by adding the following lines:
@ -1132,7 +1150,7 @@ The example plugin will tell
.Nm sudo
that the user
.Em test
is part of the non-unix group
is part of the non-Unix group
.Em mygroup .
If you add a rule that uses this group, it will affect the
.Em test
@ -1154,22 +1172,24 @@ written in Python.
A Python plugin can interact with the user using the
.Fn sudo.conv
function which displays one or more messages described by the
.Sy sudo.ConvMessage
.Dv sudo.ConvMessage
class.
This is the Python equivalent of the
.Fn conversation
function in the C sudo plugin API.
function in the C
.Nm sudo
plugin API.
A plugin should not attempt to read directly from the standard input or
the user's tty (neither of which are guaranteed to exist).
.Pp
The
.Sy sudo.ConvMessage
.Dv sudo.ConvMessage
class specifies how the user interaction should occur:
.Bd -literal -offset 4n
sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
.Ed
.Pp
.Sy sudo.ConvMessage
.Dv sudo.ConvMessage
member variables:
.Bl -tag -width 4n
.It Fa msg_type
@ -1180,7 +1200,7 @@ constants below.
.It Fa msg
The message to display to the user.
The caller must include a trailing newline in
.Li msg
.Fa msg
if one is to be displayed.
.It Fa timeout
Optional.
@ -1197,19 +1217,19 @@ To specify the message type, the following constants are available:
.Pp
.Bl -bullet -compact -offset 4n -width 1n
.It
sudo.CONV.PROMPT_ECHO_OFF
.Dv sudo.CONV.PROMPT_ECHO_OFF
.It
sudo.CONV.PROMPT_ECHO_ON
.Dv sudo.CONV.PROMPT_ECHO_ON
.It
sudo.CONV.ERROR_MSG
.Dv sudo.CONV.ERROR_MSG
.It
sudo.CONV.INFO_MSG
.Dv sudo.CONV.INFO_MSG
.It
sudo.CONV.PROMPT_MASK
.Dv sudo.CONV.PROMPT_MASK
.It
sudo.CONV.PROMPT_ECHO_OK
.Dv sudo.CONV.PROMPT_ECHO_OK
.It
sudo.CONV.PREFER_TTY
.Dv sudo.CONV.PREFER_TTY
.El
.Pp
See the
@ -1228,7 +1248,7 @@ The function arguments are as follows:
.Bl -tag -width 4n
.It Fa message(s)
One of more messages (of type
.Sy sudo.ConvMessage ) ,
.Dv sudo.ConvMessage ) ,
each describing a conversation.
At least one message is required.
.It Fa on_suspend
@ -1247,10 +1267,10 @@ The
.Fn sudo.conv
function can raise the following exceptions:
.Bl -tag -width 4n
.It Sy sudo.SudoException
.It Dv sudo.SudoException
If the conversation fails, for example when the conversation function is not
available.
.It Sy sudo.ConversationInterrupted
.It Dv sudo.ConversationInterrupted
If the conversation function returns an error, e.g., the timeout passed
or the user interrupted the conversation by pressing control-C.
.El
@ -1305,7 +1325,7 @@ debug system.
.Em Enabling debugging in sudo.conf
.Pp
To enable debug messages, add a
.Li Debug
.Em Debug
line to
.Xr sudo.conf @mansectform@
with the program set to
@ -1380,14 +1400,14 @@ one or more messages to log
.Em Available log levels:
.Bl -column "name in sudo.conf" "Python constant" "only critical messages"
.It Sy sudo.conf name Ta Sy Python constant Ta Sy description
.It crit Ta sudo.DEBUG.CRIT Ta only critical messages
.It err Ta sudo.DEBUG.ERROR Ta
.It warn Ta sudo.DEBUG.WARN Ta
.It notice Ta sudo.DEBUG.NOTICE Ta
.It diag Ta sudo.DEBUG.DIAG Ta
.It info Ta sudo.DEBUG.INFO Ta
.It trace Ta sudo.DEBUG.TRACE Ta
.It debug Ta sudo.DEBUG.DEBUG Ta very extreme verbose debugging
.It crit Ta Dv sudo.DEBUG.CRIT Ta only critical messages
.It err Ta Dv sudo.DEBUG.ERROR Ta
.It warn Ta Dv sudo.DEBUG.WARN Ta
.It notice Ta Dv sudo.DEBUG.NOTICE Ta
.It diag Ta Dv sudo.DEBUG.DIAG Ta
.It info Ta Dv sudo.DEBUG.INFO Ta
.It trace Ta Dv sudo.DEBUG.TRACE Ta
.It debug Ta Dv sudo.DEBUG.DEBUG Ta very extreme verbose debugging
.El
.Pp
.Em Using the logging module
@ -1400,11 +1420,11 @@ The log handler of sudo will map each Python log level of a message to
the appropriate sudo debug level.
The sudo debug system will only receive messages that are not filtered
out by the Python loggers.
For example, the log level of the python logger will be an additional filter
for the log messages, and is usually very different from what level is set in sudo.conf
for the sudo debug system.
For example, the log level of the python logger will be an additional
filter for the log messages, and is usually very different from
what level is set in sudo.conf for the sudo debug system.
.Ss Debug example
Sudo ships an example debug plugin by default.
Sudo ships with an example debug plugin.
To try it, register it by adding the following lines to
.Pa @sysconfdir@/sudo.conf :
.Bd -literal -offset 4n
@ -1470,12 +1490,13 @@ This is how the plugin API accepts options and settings.
.Sh PLUGIN API CHANGELOG (Python)
None yet
.Sh LIMITATIONS
Only a maximum number of 8 python I/O plugins can be loaded at once.
A maximum of 8 python I/O plugins can be loaded at once.
If
.Pa @sysconfdir@/sudo.conf
contains more, those will be rejected with a warning message.
.Pp
The Event API and the hook function API is currently not accessible for Python plugins.
The Event API and the hook function API is currently not accessible
for Python plugins.
.Sh SEE ALSO
.Xr sudo.conf @mansectform@ ,
.Xr sudo_plugin @mansectform@ ,
@ -1502,7 +1523,7 @@ If you believe you have found a bug in
you can submit a bug report at https://bugzilla.sudo.ws/
.Sh SECURITY CONSIDERATIONS
All Python plugin handling is implemented inside the
.Li python_plugin.so
.Pa python_plugin.so
dynamic plugin.
Therefore, if no Python plugin is registered in
.Xr sudo.conf @mansectform@
@ -1528,7 +1549,7 @@ accidentally importing such file would make it possible for any user
However, during development of a plugin this might not be very convenient.
The
.Xr sudo.conf @mansectform@
.Li developer_mode
.Em developer_mode
option can be used to disable it.
For example:
.Dl Set developer_mode true

View File

@ -154,7 +154,7 @@ version and exit.
.SS "Debugging sendlog"
\fBsudo_sendlog\fR
supports a flexible debugging framework that is configured via
\fRDebug\fR
\fIDebug\fR
lines in the
sudo.conf(@mansectform@)
file.

View File

@ -139,7 +139,7 @@ version and exit.
.Ss Debugging sendlog
.Nm
supports a flexible debugging framework that is configured via
.Li Debug
.Em Debug
lines in the
.Xr sudo.conf @mansectform@
file.

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDOERS.LDAP" "@mansectform@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS.LDAP" "@mansectform@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -69,16 +69,16 @@ is no need for a specialized tool to check syntax.
The
\fIsudoers\fR
configuration is contained in the
\fRou=SUDOers\fR
\(oqou=SUDOers\(cq
LDAP container.
.PP
Sudo first looks for the
\fRcn=defaults\fR
\(oqcn=defaults\(cq
entry in the SUDOers container.
If found, the multi-valued
\fRsudoOption\fR
\fIsudoOption\fR
attribute is parsed in the same manner as a global
\fRDefaults\fR
\fIDefaults\fR
line in
\fI@sysconfdir@/sudoers\fR.
In the following example, the
@ -97,7 +97,7 @@ sudoOption: env_keep+=SSH_AUTH_SOCK
.fi
.PP
The equivalent of a sudoer in LDAP is a
\fRsudoRole\fR.
\fIsudoRole\fR.
It consists of the following attributes:
.TP 6n
\fBsudoUser\fR
@ -120,36 +120,36 @@ Non-Unix group support is only available when an appropriate
\fIgroup_plugin\fR
is defined in the global
\fIdefaults\fR
\fRsudoRole\fR
\fIsudoRole\fR
object.
If a
\fRsudoUser\fR
\fIsudoUser\fR
entry is preceded by an exclamation point,
\(oq\&!\(cq,
and the entry matches, the
\fRsudoRole\fR
\fIsudoRole\fR
in which it resides will be ignored.
Negated
\fRsudoUser\fR
\fIsudoUser\fR
entries are only supported by version 1.9.9 or higher.
.TP 6n
\fBsudoHost\fR
A host name, IP address, IP network, or host netgroup (prefixed with a
\(oq+\(cq).
The special value
\fRALL\fR
\fBALL\fR
will match any host.
Host netgroups are matched using the host (both qualified and unqualified)
and domain members only; the user member is not used when matching.
If a
\fRsudoHost\fR
\fIsudoHost\fR
entry is preceded by an exclamation point,
\(oq\&!\(cq,
and the entry matches, the
\fRsudoRole\fR
\fIsudoRole\fR
in which it resides will be ignored.
Negated
\fRsudoHost\fR
\fIsudoHost\fR
entries are only supported by version 1.8.18 or higher.
.TP 6n
\fBsudoCommand\fR
@ -160,7 +160,7 @@ If a command name is preceded by an exclamation point,
the user will be prohibited from running that command.
.sp
The built-in command
\(lq\fRsudoedit\fR\(rq
\(lqsudoedit\(rq
is used to permit a user to run
\fBsudo\fR
with the
@ -169,13 +169,13 @@ option (or as
\fBsudoedit\fR).
It may take command line arguments just as a normal command does.
Unlike other commands,
\(lq\fRsudoedit\fR\(rq
\(lqsudoedit\(rq
is a built into
\fBsudo\fR
itself and must be specified in without a leading path.
.sp
The special value
\fRALL\fR
\fBALL\fR
will match any command.
.sp
If a command name is prefixed with a SHA-2 digest, it will
@ -205,7 +205,7 @@ Command digests are only supported by version 1.8.7 or higher.
\fBsudoOption\fR
Identical in function to the global options described above, but
specific to the
\fRsudoRole\fR
\fIsudoRole\fR
in which it resides.
.TP 6n
\fBsudoRunAsUser\fR
@ -217,30 +217,29 @@ or user netgroup (prefixed with a
\(oq+\(cq)
that contains a list of users that commands may be run as.
The special value
\fRALL\fR
\fBALL\fR
will match any user.
If a
\fRsudoRunAsUser\fR
\fIsudoRunAsUser\fR
entry is preceded by an exclamation point,
\(oq\&!\(cq,
and the entry matches, the
\fRsudoRole\fR
\fIsudoRole\fR
in which it resides will be ignored.
If
\fRsudoRunAsUser\fR
\fIsudoRunAsUser\fR
is specified but empty, it will match the invoking user.
If neither
\fRsudoRunAsUser\fR
\fIsudoRunAsUser\fR
nor
\fRsudoRunAsGroup\fR
\fIsudoRunAsGroup\fR
are present, the value of the
\fIrunas_default\fR
\fRsudoOption\fR
is used (defaults to
\fR@runas_default@\fR).
\fIsudoOption\fR
is used (defaults to @runas_default@).
.sp
The
\fRsudoRunAsUser\fR
\fIsudoRunAsUser\fR
attribute is only available in
\fBsudo\fR
versions
@ -248,10 +247,10 @@ versions
Older versions of
\fBsudo\fR
use the
\fRsudoRunAs\fR
\fIsudoRunAs\fR
attribute instead.
Negated
\fRsudoRunAsUser\fR
\fIsudoRunAsUser\fR
entries are only supported by version 1.8.26 or higher.
.TP 6n
\fBsudoRunAsGroup\fR
@ -259,34 +258,34 @@ A Unix group or group-ID (prefixed with
\(oq#\(cq)
that commands may be run as.
The special value
\fRALL\fR
\fBALL\fR
will match any group.
If a
\fRsudoRunAsGroup\fR
\fIsudoRunAsGroup\fR
entry is preceded by an exclamation point,
\(oq\&!\(cq,
and the entry matches, the
\fRsudoRole\fR
\fIsudoRole\fR
in which it resides will be ignored.
.sp
The
\fRsudoRunAsGroup\fR
\fIsudoRunAsGroup\fR
attribute is only available in
\fBsudo\fR
versions
1.7.0 and higher.
Negated
\fRsudoRunAsGroup\fR
\fIsudoRunAsGroup\fR
entries are only supported by version 1.8.26 or higher.
.TP 6n
\fBsudoNotBefore\fR
A timestamp in the form
\fRyyyymmddHHMMSSZ\fR
\(oqyyyymmddHHMMSSZ\(cq
that can be used to provide a start date/time for when the
\fRsudoRole\fR
\fIsudoRole\fR
will be valid.
If multiple
\fRsudoNotBefore\fR
\fIsudoNotBefore\fR
entries are present, the earliest is used.
Timestamps must be in Coordinated Universal Time (UTC),
not the local timezone.
@ -294,7 +293,7 @@ The minute and seconds portions are optional, but some LDAP servers
require that they be present (contrary to the RFC).
.sp
The
\fRsudoNotBefore\fR
\fIsudoNotBefore\fR
attribute is only available in
\fBsudo\fR
versions 1.7.5 and higher and must be explicitly enabled via the
@ -304,12 +303,12 @@ option in
.TP 6n
\fBsudoNotAfter\fR
A timestamp in the form
\fRyyyymmddHHMMSSZ\fR
\(oqyyyymmddHHMMSSZ\(cq
that indicates an expiration date/time, after which the
\fRsudoRole\fR
\fIsudoRole\fR
will no longer be valid.
If multiple
\fRsudoNotAfter\fR
\fIsudoNotAfter\fR
entries are present, the last one is used.
Timestamps must be in Coordinated Universal Time (UTC),
not the local timezone.
@ -317,7 +316,7 @@ The minute and seconds portions are optional, but some LDAP servers
require that they be present (contrary to the RFC).
.sp
The
\fRsudoNotAfter\fR
\fIsudoNotAfter\fR
attribute is only available in
\fBsudo\fR
versions
@ -328,26 +327,26 @@ option in
.TP 6n
\fBsudoOrder\fR
The
\fRsudoRole\fR
\fIsudoRole\fR
entries retrieved from the LDAP directory have no inherent order.
The
\fRsudoOrder\fR
\fIsudoOrder\fR
attribute is an integer (or floating point value for LDAP servers
that support it) that is used to sort the matching entries.
This allows LDAP-based sudoers entries to more closely mimic the behavior
of the sudoers file, where the order of the entries influences the result.
If multiple entries match, the entry with the highest
\fRsudoOrder\fR
\fIsudoOrder\fR
attribute is chosen.
This corresponds to the
\(lqlast match\(rq
behavior of the sudoers file.
If the
\fRsudoOrder\fR
\fIsudoOrder\fR
attribute is not present, a value of 0 is assumed.
.sp
The
\fRsudoOrder\fR
\fIsudoOrder\fR
attribute is only available in
\fBsudo\fR
versions 1.7.5 and higher.
@ -355,12 +354,12 @@ versions 1.7.5 and higher.
Each attribute listed above should contain a single value, but there
may be multiple instances of each attribute type.
A
\fRsudoRole\fR
\fIsudoRole\fR
must contain at least one
\fRsudoUser\fR,
\fRsudoHost\fR,
\fIsudoUser\fR,
\fIsudoHost\fR,
and
\fRsudoCommand\fR.
\fIsudoCommand\fR.
.PP
The following example allows users in group wheel to run any command
on any host via
@ -384,7 +383,7 @@ The first query is to parse the global options.
The second is to match against the user's name and the groups that
the user belongs to.
(The special
\fRALL\fR
\fBALL\fR
tag is matched in this query too.)
If no match is returned for the user's name and groups, a third
query returns all entries containing user netgroups and other
@ -411,12 +410,12 @@ are as follows:
.TP 5n
1.\&
Match all
\fRnisNetgroup\fR
\fInisNetgroup\fR
records with a
\fRnisNetgroupTriple\fR
\fInisNetgroupTriple\fR
containing the user, host, and NIS domain.
The query will match
\fRnisNetgroupTriple\fR
\fInisNetgroupTriple\fR
entries with either the short or long form of the host name or
no host name specified in the tuple.
If the NIS domain is set, the query will match only match entries
@ -425,13 +424,13 @@ If the NIS domain is
\fInot\fR
set, a wildcard is used to match any domain name but be aware that the
NIS schema used by some LDAP servers may not support wild cards for
\fRnisNetgroupTriple\fR.
\fInisNetgroupTriple\fR.
.TP 5n
2.\&
Repeated queries are performed to find any nested
\fRnisNetgroup\fR
\fInisNetgroup\fR
records with a
\fRmemberNisNetgroup\fR
\fImemberNisNetgroup\fR
entry that refers to an already-matched record.
.PP
For sites with a large number of netgroups, using
@ -465,7 +464,7 @@ returned in any specific order.
.PP
The order in which different entries are applied can be controlled
using the
\fRsudoOrder\fR
\fIsudoOrder\fR
attribute, but there is no way to guarantee the order of attributes
within a specific entry.
If there are conflicting command rules in an entry, the negative
@ -519,18 +518,18 @@ These cannot be converted automatically.
For example, a Cmnd_Alias in a
\fIsudoers\fR
file may be converted to a
\fRsudoRole\fR
\fIsudoRole\fR
that contains multiple commands.
Multiple users and/or groups may be assigned to the
\fRsudoRole\fR.
\fIsudoRole\fR.
.PP
Also, host, user, runas, and command-based
\fRDefaults\fR
\fIDefaults\fR
entries are not supported.
However, a
\fRsudoRole\fR
\fIsudoRole\fR
may contain one or more
\fRsudoOption\fR
\fIsudoOption\fR
attributes which can often serve the same purpose.
.PP
Consider the following
@ -590,7 +589,7 @@ Using a Unix group or netgroup in PAGERS rather than listing each
user would make this easier to maintain.
.PP
Per-user
\fRDefaults\fR
\fIDefaults\fR
entries can be emulated by using one or more sudoOption attributes
in a sudoRole.
Consider the following
@ -637,7 +636,7 @@ LDAP support, the
schema must be
installed on your LDAP server.
In addition, be sure to index the
\fRsudoUser\fR
\fIsudoUser\fR
attribute.
.PP
The
@ -797,53 +796,51 @@ The default value is protocol version 3.
\fBNETGROUP_BASE\fR \fIbase\fR
The base DN to use when performing LDAP netgroup queries.
Typically this is of the form
\fRou=netgroup,dc=my-domain,dc=com\fR
for the domain
\fRmy-domain.com\fR.
\(oqou=netgroup,dc=my-domain,dc=com\(cq
for the domain my-domain.com.
Multiple
\fBNETGROUP_BASE\fR
lines may be specified, in which case they are queried in the order specified.
.sp
This option can be used to query a user's netgroups directly via LDAP
which is usually faster than fetching every
\fRsudoRole\fR
\fIsudoRole\fR
object containing a
\fRsudoUser\fR
\fIsudoUser\fR
that begins with a
\(oq+\(cq
prefix.
The NIS schema used by some LDAP servers need a modification to
support querying the
\fRnisNetgroup\fR
\fInisNetgroup\fR
object by its
\fRnisNetgroupTriple\fR
\fInisNetgroupTriple\fR
member.
OpenLDAP's
\fBslapd\fR
requires the following change to the
\fRnisNetgroupTriple\fR
\fInisNetgroupTriple\fR
attribute:
.nf
.sp
.RS 10n
attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
DESC 'Netgroup triple'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
DESC 'Netgroup triple'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
.RE
.fi
.TP 6n
\fBNETGROUP_SEARCH_FILTER\fR \fIldap_filter\fR
An LDAP filter which is used to restrict the set of records returned
when performing an LDAP netgroup query.
Typically, this is of the
form
\fRattribute=value\fR
Typically, this is of the form
\(oqattribute=value\(cq
or
\fR(&(attribute=value)(attribute2=value2))\fR.
\(oq(&(attribute=value)(attribute2=value2))\(cq.
The default search filter is:
\fRobjectClass=nisNetgroup\fR.
\(oqobjectClass=nisNetgroup\(cq.
If
\fIldap_filter\fR
is omitted, no search filter will be used.
@ -928,10 +925,10 @@ This option is only relevant when using SASL authentication.
If the
\fBSSL\fR
parameter is set to
\fRon\fR,
\fRtrue\fR,
\fIon\fR,
\fItrue\fR,
or
\fRyes\fR
\fIyes\fR
TLS (SSL) encryption is always used when communicating with the LDAP server.
Typically, this involves connecting to the server on port 636 (ldaps).
.TP 6n
@ -939,7 +936,7 @@ Typically, this involves connecting to the server on port 636 (ldaps).
If the
\fBSSL\fR
parameter is set to
\fRstart_tls\fR,
\fIstart_tls\fR,
the LDAP server connection is initiated normally and TLS encryption is
begun before the bind credentials are sent.
This has the advantage of not requiring a dedicated port for encrypted
@ -953,9 +950,8 @@ The base DN to use when performing
\fBsudo\fR
LDAP queries.
Typically this is of the form
\fRou=SUDOers,dc=my-domain,dc=com\fR
for the domain
\fRmy-domain.com\fR.
\(oqou=SUDOers,dc=my-domain,dc=com\(cq
for the domain my-domain.com.
Multiple
\fBSUDOERS_BASE\fR
lines may be specified, in which case they are queried in the order specified.
@ -997,20 +993,20 @@ when performing a
LDAP query.
Typically, this is of the
form
\fRattribute=value\fR
\(oqattribute=value\(cq
or
\fR(&(attribute=value)(attribute2=value2))\fR.
\(oq(&(attribute=value)(attribute2=value2))\(cq.
The default search filter is:
\fRobjectClass=sudoRole\fR.
\(oqobjectClass=sudoRole\(cq.
If
\fIldap_filter\fR
is omitted, no search filter will be used.
.TP 6n
\fBSUDOERS_TIMED\fR \fIon/true/yes/off/false/no\fR
Whether or not to evaluate the
\fRsudoNotBefore\fR
\fIsudoNotBefore\fR
and
\fRsudoNotAfter\fR
\fIsudoNotAfter\fR
attributes that implement time-dependent sudoers entries.
.TP 6n
\fBTIMELIMIT\fR \fIseconds\fR
@ -1062,11 +1058,11 @@ The certificate type depends on the LDAP libraries used.
.PD 0
.TP 6n
OpenLDAP:
\fRtls_cert /etc/ssl/client_cert.pem\fR
\(oqtls_cert /etc/ssl/client_cert.pem\(cq
.PD
.TP 6n
Netscape-derived:
\fRtls_cert /var/ldap/cert7.db\fR
\(oqtls_cert /var/ldap/cert7.db\(cq
.TP 6n
IBM LDAP:
Unused, the key database specified by
@ -1106,14 +1102,14 @@ The key type depends on the LDAP libraries used.
.PD 0
.TP 6n
OpenLDAP:
\fRtls_key /etc/ssl/client_key.pem\fR
\(oqtls_key /etc/ssl/client_key.pem\(cq
.PD
.TP 6n
Netscape-derived:
\fRtls_key /var/ldap/key3.db\fR
\(oqtls_key /var/ldap/key3.db\(cq
.TP 6n
IBM LDAP:
\fRtls_key /usr/ldap/ldapkey.kdb\fR
\(oqtls_key /usr/ldap/ldapkey.kdb\(cq
.PP
When using IBM LDAP libraries, this file may also contain
Certificate Authority and client certificates and may be encrypted.
@ -1171,15 +1167,15 @@ The
must have the same path as the file specified by
\fBTLS_KEY\fR,
but use a
\fR.sth\fR
\(oq.sth\(cq
file extension instead of
\fR.kdb\fR,
e.g.,
\fRldapkey.sth\fR.
\(oq.kdb\(cq,
for example
\(oqldapkey.sth\(cq.
The default
\fRldapkey.kdb\fR
\(oqldapkey.kdb\(cq
that ships with the IBM Tivoli Directory Server is encrypted with the password
\fRssl_password\fR.
\(oqssl_password\(cq.
The
\fIgsk8capicmd\fR
utility can be used to manage the key database and create a
@ -1251,9 +1247,9 @@ the latter being for servers that support TLS (SSL) encryption.
If no
\fIport\fR
is specified, the default is port 389 for
\fRldap://\fR
\(oqldap://\(cq
or port 636 for
\fRldaps://\fR.
\(oqldaps://\(cq.
If no
\fIhostname\fR
is specified,
@ -1266,9 +1262,9 @@ lines are treated identically to a
\fBURI\fR
line containing multiple entries.
Only systems using the OpenSSL libraries support the mixing of
\fRldap://\fR
\(oqldap://\(cq
and
\fRldaps://\fR
\(oqldaps://\(cq
URIs.
Both the Netscape-derived and IBM LDAP libraries used on most commercial
versions of Unix are only capable of supporting one or the other.
@ -1297,13 +1293,13 @@ to specify the
\fIsudoers\fR
search order.
Sudo looks for a line beginning with
\fRsudoers\fR:
\fIsudoers\fR:
and uses this to determine the search order.
By default,
\fBsudo\fR
does not stop searching after the first match and later matches take
precedence over earlier ones (unless
\fR[SUCCESS=return]\fR
\(oq[SUCCESS=return]\(cq
is used, see below).
The following sources are recognized:
.PP
@ -1322,14 +1318,14 @@ read sudoers from LDAP
In addition, a subset of
\fInsswitch.conf\fR-style
action statements is supported, specifically
\fR[SUCCESS=return]\fR
\(oq[SUCCESS=return]\(cq
and
\fR[NOTFOUND=return]\fR.
\(oq[NOTFOUND=return]\(cq.
These will unconditionally terminate the search if the user was either
found
(\fR[SUCCESS=return]\fR)
\(oq[SUCCESS=return]\(cq
or not found
(\fR[NOTFOUND=return]\fR)
\(oq[NOTFOUND=return]\(cq
in the immediately preceding source.
Other action statements tokens are not supported, nor is test
negation with
@ -1420,11 +1416,11 @@ sudoers = ldap = auth, files
.fi
.PP
In the above example, the
\fRauth\fR
\fIauth\fR
qualifier only affects user lookups; both LDAP and
\fIsudoers\fR
will be queried for
\fRDefaults\fR
\fIDefaults\fR
entries.
.PP
If the
@ -1449,9 +1445,9 @@ rules.
To use SSSD as the
\fIsudoers\fR
source, you should use
\fRsss\fR
\fIsss\fR
instead of
\fRldap\fR
\fIldap\fR
for the sudoers entry in
\fI@nsswitch_conf@\fR.
The
@ -1595,7 +1591,7 @@ Simply copy
it to the schema directory (e.g.,
\fI/etc/openldap/schema\fR),
add the proper
\fRinclude\fR
\fIinclude\fR
line in
\fIslapd.conf\fR
and restart
@ -1610,9 +1606,9 @@ file instead.
attributetype ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SUBSTR caseExactSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
@ -1642,14 +1638,14 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.5
attributetype ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'
@ -1666,11 +1662,11 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.9
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributetype ( 1.3.6.1.4.1.15953.9.1.10
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
DESC 'Sudoer Entries'

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDOERS.LDAP @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -67,16 +67,16 @@ is no need for a specialized tool to check syntax.
The
.Em sudoers
configuration is contained in the
.Li ou=SUDOers
.Ql ou=SUDOers
LDAP container.
.Pp
Sudo first looks for the
.Li cn=defaults
.Ql cn=defaults
entry in the SUDOers container.
If found, the multi-valued
.Li sudoOption
.Em sudoOption
attribute is parsed in the same manner as a global
.Li Defaults
.Em Defaults
line in
.Pa @sysconfdir@/sudoers .
In the following example, the
@ -92,7 +92,7 @@ sudoOption: env_keep+=SSH_AUTH_SOCK
.Ed
.Pp
The equivalent of a sudoer in LDAP is a
.Li sudoRole .
.Em sudoRole .
It consists of the following attributes:
.Bl -tag -width 4n
.It Sy sudoUser
@ -115,35 +115,35 @@ Non-Unix group support is only available when an appropriate
.Em group_plugin
is defined in the global
.Em defaults
.Li sudoRole
.Em sudoRole
object.
If a
.Li sudoUser
.Em sudoUser
entry is preceded by an exclamation point,
.Ql \&! ,
and the entry matches, the
.Li sudoRole
.Em sudoRole
in which it resides will be ignored.
Negated
.Li sudoUser
.Em sudoUser
entries are only supported by version 1.9.9 or higher.
.It Sy sudoHost
A host name, IP address, IP network, or host netgroup (prefixed with a
.Ql + ) .
The special value
.Li ALL
.Sy ALL
will match any host.
Host netgroups are matched using the host (both qualified and unqualified)
and domain members only; the user member is not used when matching.
If a
.Li sudoHost
.Em sudoHost
entry is preceded by an exclamation point,
.Ql \&! ,
and the entry matches, the
.Li sudoRole
.Em sudoRole
in which it resides will be ignored.
Negated
.Li sudoHost
.Em sudoHost
entries are only supported by version 1.8.18 or higher.
.It Sy sudoCommand
A fully-qualified Unix command name with optional command line arguments,
@ -153,7 +153,7 @@ If a command name is preceded by an exclamation point,
the user will be prohibited from running that command.
.Pp
The built-in command
.Dq Li sudoedit
.Dq sudoedit
is used to permit a user to run
.Nm sudo
with the
@ -162,13 +162,13 @@ option (or as
.Nm sudoedit ) .
It may take command line arguments just as a normal command does.
Unlike other commands,
.Dq Li sudoedit
.Dq sudoedit
is a built into
.Nm sudo
itself and must be specified in without a leading path.
.Pp
The special value
.Li ALL
.Sy ALL
will match any command.
.Pp
If a command name is prefixed with a SHA-2 digest, it will
@ -192,7 +192,7 @@ Command digests are only supported by version 1.8.7 or higher.
.It Sy sudoOption
Identical in function to the global options described above, but
specific to the
.Li sudoRole
.Em sudoRole
in which it resides.
.It Sy sudoRunAsUser
A user name or user-ID (prefixed with
@ -203,30 +203,29 @@ or user netgroup (prefixed with a
.Ql + )
that contains a list of users that commands may be run as.
The special value
.Li ALL
.Sy ALL
will match any user.
If a
.Li sudoRunAsUser
.Em sudoRunAsUser
entry is preceded by an exclamation point,
.Ql \&! ,
and the entry matches, the
.Li sudoRole
.Em sudoRole
in which it resides will be ignored.
If
.Li sudoRunAsUser
.Em sudoRunAsUser
is specified but empty, it will match the invoking user.
If neither
.Li sudoRunAsUser
.Em sudoRunAsUser
nor
.Li sudoRunAsGroup
.Em sudoRunAsGroup
are present, the value of the
.Em runas_default
.Li sudoOption
is used (defaults to
.Li @runas_default@ ) .
.Em sudoOption
is used (defaults to @runas_default@).
.Pp
The
.Li sudoRunAsUser
.Em sudoRunAsUser
attribute is only available in
.Nm sudo
versions
@ -234,43 +233,43 @@ versions
Older versions of
.Nm sudo
use the
.Li sudoRunAs
.Em sudoRunAs
attribute instead.
Negated
.Li sudoRunAsUser
.Em sudoRunAsUser
entries are only supported by version 1.8.26 or higher.
.It Sy sudoRunAsGroup
A Unix group or group-ID (prefixed with
.Ql # )
that commands may be run as.
The special value
.Li ALL
.Sy ALL
will match any group.
If a
.Li sudoRunAsGroup
.Em sudoRunAsGroup
entry is preceded by an exclamation point,
.Ql \&! ,
and the entry matches, the
.Li sudoRole
.Em sudoRole
in which it resides will be ignored.
.Pp
The
.Li sudoRunAsGroup
.Em sudoRunAsGroup
attribute is only available in
.Nm sudo
versions
1.7.0 and higher.
Negated
.Li sudoRunAsGroup
.Em sudoRunAsGroup
entries are only supported by version 1.8.26 or higher.
.It Sy sudoNotBefore
A timestamp in the form
.Li yyyymmddHHMMSSZ
.Ql yyyymmddHHMMSSZ
that can be used to provide a start date/time for when the
.Li sudoRole
.Em sudoRole
will be valid.
If multiple
.Li sudoNotBefore
.Em sudoNotBefore
entries are present, the earliest is used.
Timestamps must be in Coordinated Universal Time (UTC),
not the local timezone.
@ -278,7 +277,7 @@ The minute and seconds portions are optional, but some LDAP servers
require that they be present (contrary to the RFC).
.Pp
The
.Li sudoNotBefore
.Em sudoNotBefore
attribute is only available in
.Nm sudo
versions 1.7.5 and higher and must be explicitly enabled via the
@ -287,12 +286,12 @@ option in
.Pa @ldap_conf@ .
.It Sy sudoNotAfter
A timestamp in the form
.Li yyyymmddHHMMSSZ
.Ql yyyymmddHHMMSSZ
that indicates an expiration date/time, after which the
.Li sudoRole
.Em sudoRole
will no longer be valid.
If multiple
.Li sudoNotAfter
.Em sudoNotAfter
entries are present, the last one is used.
Timestamps must be in Coordinated Universal Time (UTC),
not the local timezone.
@ -300,7 +299,7 @@ The minute and seconds portions are optional, but some LDAP servers
require that they be present (contrary to the RFC).
.Pp
The
.Li sudoNotAfter
.Em sudoNotAfter
attribute is only available in
.Nm sudo
versions
@ -310,26 +309,26 @@ option in
.Pa @ldap_conf@ .
.It Sy sudoOrder
The
.Li sudoRole
.Em sudoRole
entries retrieved from the LDAP directory have no inherent order.
The
.Li sudoOrder
.Em sudoOrder
attribute is an integer (or floating point value for LDAP servers
that support it) that is used to sort the matching entries.
This allows LDAP-based sudoers entries to more closely mimic the behavior
of the sudoers file, where the order of the entries influences the result.
If multiple entries match, the entry with the highest
.Li sudoOrder
.Em sudoOrder
attribute is chosen.
This corresponds to the
.Dq last match
behavior of the sudoers file.
If the
.Li sudoOrder
.Em sudoOrder
attribute is not present, a value of 0 is assumed.
.Pp
The
.Li sudoOrder
.Em sudoOrder
attribute is only available in
.Nm sudo
versions 1.7.5 and higher.
@ -338,12 +337,12 @@ versions 1.7.5 and higher.
Each attribute listed above should contain a single value, but there
may be multiple instances of each attribute type.
A
.Li sudoRole
.Em sudoRole
must contain at least one
.Li sudoUser ,
.Li sudoHost ,
.Em sudoUser ,
.Em sudoHost ,
and
.Li sudoCommand .
.Em sudoCommand .
.Pp
The following example allows users in group wheel to run any command
on any host via
@ -364,7 +363,7 @@ The first query is to parse the global options.
The second is to match against the user's name and the groups that
the user belongs to.
(The special
.Li ALL
.Sy ALL
tag is matched in this query too.)
If no match is returned for the user's name and groups, a third
query returns all entries containing user netgroups and other
@ -391,12 +390,12 @@ are as follows:
.Bl -enum
.It
Match all
.Li nisNetgroup
.Em nisNetgroup
records with a
.Li nisNetgroupTriple
.Em nisNetgroupTriple
containing the user, host, and NIS domain.
The query will match
.Li nisNetgroupTriple
.Em nisNetgroupTriple
entries with either the short or long form of the host name or
no host name specified in the tuple.
If the NIS domain is set, the query will match only match entries
@ -405,12 +404,12 @@ If the NIS domain is
.Em not
set, a wildcard is used to match any domain name but be aware that the
NIS schema used by some LDAP servers may not support wild cards for
.Li nisNetgroupTriple .
.Em nisNetgroupTriple .
.It
Repeated queries are performed to find any nested
.Li nisNetgroup
.Em nisNetgroup
records with a
.Li memberNisNetgroup
.Em memberNisNetgroup
entry that refers to an already-matched record.
.El
.Pp
@ -445,7 +444,7 @@ returned in any specific order.
.Pp
The order in which different entries are applied can be controlled
using the
.Li sudoOrder
.Em sudoOrder
attribute, but there is no way to guarantee the order of attributes
within a specific entry.
If there are conflicting command rules in an entry, the negative
@ -496,18 +495,18 @@ These cannot be converted automatically.
For example, a Cmnd_Alias in a
.Em sudoers
file may be converted to a
.Li sudoRole
.Em sudoRole
that contains multiple commands.
Multiple users and/or groups may be assigned to the
.Li sudoRole .
.Em sudoRole .
.Pp
Also, host, user, runas, and command-based
.Li Defaults
.Em Defaults
entries are not supported.
However, a
.Li sudoRole
.Em sudoRole
may contain one or more
.Li sudoOption
.Em sudoOption
attributes which can often serve the same purpose.
.Pp
Consider the following
@ -561,7 +560,7 @@ Using a Unix group or netgroup in PAGERS rather than listing each
user would make this easier to maintain.
.Pp
Per-user
.Li Defaults
.Em Defaults
entries can be emulated by using one or more sudoOption attributes
in a sudoRole.
Consider the following
@ -602,7 +601,7 @@ LDAP support, the
schema must be
installed on your LDAP server.
In addition, be sure to index the
.Li sudoUser
.Em sudoUser
attribute.
.Pp
The
@ -748,49 +747,47 @@ The default value is protocol version 3.
.It Sy NETGROUP_BASE Ar base
The base DN to use when performing LDAP netgroup queries.
Typically this is of the form
.Li ou=netgroup,dc=my-domain,dc=com
for the domain
.Li my-domain.com .
.Ql ou=netgroup,dc=my-domain,dc=com
for the domain my-domain.com.
Multiple
.Sy NETGROUP_BASE
lines may be specified, in which case they are queried in the order specified.
.Pp
This option can be used to query a user's netgroups directly via LDAP
which is usually faster than fetching every
.Li sudoRole
.Em sudoRole
object containing a
.Li sudoUser
.Em sudoUser
that begins with a
.Ql +
prefix.
The NIS schema used by some LDAP servers need a modification to
support querying the
.Li nisNetgroup
.Em nisNetgroup
object by its
.Li nisNetgroupTriple
.Em nisNetgroupTriple
member.
OpenLDAP's
.Sy slapd
requires the following change to the
.Li nisNetgroupTriple
.Em nisNetgroupTriple
attribute:
.Bd -literal -offset 4n
attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
DESC 'Netgroup triple'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
DESC 'Netgroup triple'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
.Ed
.It Sy NETGROUP_SEARCH_FILTER Ar ldap_filter
An LDAP filter which is used to restrict the set of records returned
when performing an LDAP netgroup query.
Typically, this is of the
form
.Li attribute=value
Typically, this is of the form
.Ql attribute=value
or
.Li (&(attribute=value)(attribute2=value2)) .
.Ql (&(attribute=value)(attribute2=value2)) .
The default search filter is:
.Li objectClass=nisNetgroup .
.Ql objectClass=nisNetgroup .
If
.Ar ldap_filter
is omitted, no search filter will be used.
@ -867,17 +864,17 @@ This option is only relevant when using SASL authentication.
If the
.Sy SSL
parameter is set to
.Li on ,
.Li true ,
.Em on ,
.Em true ,
or
.Li yes
.Em yes
TLS (SSL) encryption is always used when communicating with the LDAP server.
Typically, this involves connecting to the server on port 636 (ldaps).
.It Sy SSL Ar start_tls
If the
.Sy SSL
parameter is set to
.Li start_tls ,
.Em start_tls ,
the LDAP server connection is initiated normally and TLS encryption is
begun before the bind credentials are sent.
This has the advantage of not requiring a dedicated port for encrypted
@ -890,9 +887,8 @@ The base DN to use when performing
.Nm sudo
LDAP queries.
Typically this is of the form
.Li ou=SUDOers,dc=my-domain,dc=com
for the domain
.Li my-domain.com .
.Ql ou=SUDOers,dc=my-domain,dc=com
for the domain my-domain.com.
Multiple
.Sy SUDOERS_BASE
lines may be specified, in which case they are queried in the order specified.
@ -932,19 +928,19 @@ when performing a
LDAP query.
Typically, this is of the
form
.Li attribute=value
.Ql attribute=value
or
.Li (&(attribute=value)(attribute2=value2)) .
.Ql (&(attribute=value)(attribute2=value2)) .
The default search filter is:
.Li objectClass=sudoRole .
.Ql objectClass=sudoRole .
If
.Ar ldap_filter
is omitted, no search filter will be used.
.It Sy SUDOERS_TIMED Ar on/true/yes/off/false/no
Whether or not to evaluate the
.Li sudoNotBefore
.Em sudoNotBefore
and
.Li sudoNotAfter
.Em sudoNotAfter
attributes that implement time-dependent sudoers entries.
.It Sy TIMELIMIT Ar seconds
The
@ -987,9 +983,9 @@ be used to authenticate the client to the LDAP server.
The certificate type depends on the LDAP libraries used.
.Bl -tag -width 4n
.It OpenLDAP:
.Li tls_cert /etc/ssl/client_cert.pem
.Ql tls_cert /etc/ssl/client_cert.pem
.It Netscape-derived:
.Li tls_cert /var/ldap/cert7.db
.Ql tls_cert /var/ldap/cert7.db
.It IBM LDAP:
Unused, the key database specified by
.Sy TLS_KEY
@ -1023,11 +1019,11 @@ The private key must not be password-protected.
The key type depends on the LDAP libraries used.
.Bl -tag -width 4n
.It OpenLDAP:
.Li tls_key /etc/ssl/client_key.pem
.Ql tls_key /etc/ssl/client_key.pem
.It Netscape-derived:
.Li tls_key /var/ldap/key3.db
.Ql tls_key /var/ldap/key3.db
.It IBM LDAP:
.Li tls_key /usr/ldap/ldapkey.kdb
.Ql tls_key /usr/ldap/ldapkey.kdb
.El
.Pp
When using IBM LDAP libraries, this file may also contain
@ -1079,15 +1075,15 @@ The
must have the same path as the file specified by
.Sy TLS_KEY ,
but use a
.Li .sth
.Ql .sth
file extension instead of
.Li .kdb ,
e.g.,
.Li ldapkey.sth .
.Ql .kdb ,
for example
.Ql ldapkey.sth .
The default
.Li ldapkey.kdb
.Ql ldapkey.kdb
that ships with the IBM Tivoli Directory Server is encrypted with the password
.Li ssl_password .
.Ql ssl_password .
The
.Em gsk8capicmd
utility can be used to manage the key database and create a
@ -1149,9 +1145,9 @@ the latter being for servers that support TLS (SSL) encryption.
If no
.Em port
is specified, the default is port 389 for
.Li ldap://
.Ql ldap://
or port 636 for
.Li ldaps:// .
.Ql ldaps:// .
If no
.Em hostname
is specified,
@ -1164,9 +1160,9 @@ lines are treated identically to a
.Sy URI
line containing multiple entries.
Only systems using the OpenSSL libraries support the mixing of
.Li ldap://
.Ql ldap://
and
.Li ldaps://
.Ql ldaps://
URIs.
Both the Netscape-derived and IBM LDAP libraries used on most commercial
versions of Unix are only capable of supporting one or the other.
@ -1194,13 +1190,13 @@ to specify the
.Em sudoers
search order.
Sudo looks for a line beginning with
.Li sudoers :
.Em sudoers :
and uses this to determine the search order.
By default,
.Nm sudo
does not stop searching after the first match and later matches take
precedence over earlier ones (unless
.Li [SUCCESS=return]
.Ql [SUCCESS=return]
is used, see below).
The following sources are recognized:
.Pp
@ -1215,14 +1211,14 @@ read sudoers from LDAP
In addition, a subset of
.Pa nsswitch.conf Ns -style
action statements is supported, specifically
.Li [SUCCESS=return]
.Ql [SUCCESS=return]
and
.Li [NOTFOUND=return] .
.Ql [NOTFOUND=return] .
These will unconditionally terminate the search if the user was either
found
.Pq Li [SUCCESS=return]
.Ql [SUCCESS=return]
or not found
.Pq Li [NOTFOUND=return]
.Ql [NOTFOUND=return]
in the immediately preceding source.
Other action statements tokens are not supported, nor is test
negation with
@ -1292,11 +1288,11 @@ sudoers = ldap = auth, files
.Ed
.Pp
In the above example, the
.Li auth
.Em auth
qualifier only affects user lookups; both LDAP and
.Em sudoers
will be queried for
.Li Defaults
.Em Defaults
entries.
.Pp
If the
@ -1318,9 +1314,9 @@ rules.
To use SSSD as the
.Em sudoers
source, you should use
.Li sss
.Em sss
instead of
.Li ldap
.Em ldap
for the sudoers entry in
.Pa @nsswitch_conf@ .
The
@ -1461,7 +1457,7 @@ Simply copy
it to the schema directory (e.g.,
.Pa /etc/openldap/schema ) ,
add the proper
.Li include
.Em include
line in
.Pa slapd.conf
and restart
@ -1474,9 +1470,9 @@ file instead.
attributetype ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SUBSTR caseExactSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
@ -1506,14 +1502,14 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.5
attributetype ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'
@ -1530,11 +1526,11 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.9
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributetype ( 1.3.6.1.4.1.15953.9.1.10
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
DESC 'Sudoer Entries'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDOERS_TIMESTAMP" "@mansectform@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS_TIMESTAMP" "@mansectform@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -29,7 +29,7 @@ plugin uses per-user time stamp files for credential caching.
Once a user has been authenticated, they may use
\fBsudo\fR
without a password for a short period of time
(\fR@timeout@\fR
(\fI@timeout@\fR
minutes unless overridden by the
\fItimestamp_timeout\fR
option)

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDOERS_TIMESTAMP @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -29,7 +29,7 @@ Once a user has been authenticated, they may use
.Nm sudo
without a password for a short period of time
.Po
.Li @timeout@
.Em @timeout@
minutes unless overridden by the
.Em timestamp_timeout
option
@ -94,19 +94,19 @@ same file but are not inter-operable.
The size of the record in bytes.
.It type
The record type, currently
.Li TS_GLOBAL ,
.Li TS_TTY ,
.Dv TS_GLOBAL ,
.Dv TS_TTY ,
or
.Li TS_PPID .
.Dv TS_PPID .
.It flags
Zero or more record flags which can be bit-wise ORed together.
Supported flags are
.Li TS_DISABLED ,
.Dv TS_DISABLED ,
for records disabled via
.Nm sudo
.Fl k
and
.Li TS_ANYUID ,
.Dv TS_ANYUID ,
which is used only when matching records.
.It auth_uid
The user-ID that was used for authentication.
@ -120,12 +120,12 @@ the default runas user or the target user.
.It sid
The ID of the user's terminal session, if present.
The session ID is only used when matching records of type
.Li TS_TTY .
.Dv TS_TTY .
.It start_time
The start time of the session leader for records of type
.Li TS_TTY
.Dv TS_TTY
or of the parent process for records of type
.Li TS_PPID .
.Dv TS_PPID .
The
.Em start_time
is used to help prevent re-use of a time stamp record after a
@ -157,10 +157,10 @@ option, no password is required.
.It u.ttydev
The device number of the terminal associated with the session for
records of type
.Li TS_TTY .
.Dv TS_TTY .
.It u.ppid
The ID of the parent process for records of type
.Li TS_PPID .
.Dv TS_PPID .
.El
.Sh LOCKING
In
@ -174,7 +174,7 @@ of the entire file and the lock is held for a longer period of time.
This scheme is described below.
.Pp
The first record in the time stamp file is of type
.Li TS_LOCKEXCL
.Dv TS_LOCKEXCL
and is used as a
.Em lock
record to prevent more than one
@ -182,7 +182,7 @@ record to prevent more than one
process from adding a new record at the same time.
Once the desired time stamp record has been located or created (and
locked), the
.Li TS_LOCKEXCL
.Dv TS_LOCKEXCL
record is unlocked.
The lock on the individual time stamp record, however, is held until
authentication is complete.
@ -192,7 +192,7 @@ to avoid prompting for a password multiple times when it
is used more than once in a pipeline.
.Pp
Records of type
.Li TS_GLOBAL
.Dv TS_GLOBAL
cannot be locked for a long period of time since doing so would
interfere with other
.Nm sudo

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.TH "SUDOREPLAY" "@mansectsu@" "February 16, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.TH "SUDOREPLAY" "@mansectsu@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
@ -50,7 +50,7 @@ The
\fIID\fR
should either be a six character sequence of digits and
upper case letters, e.g.,
\fR0100A5\fR
\(lq0100A5\(rq
or a path name.
The
\fIID\fR
@ -76,8 +76,10 @@ with
enabled in the
\fIsudoers\fR
file, a
\fRTSID=ID\fR
string is logged via syslog or to the
\(lqTSID=ID\(rq
string is logged via
syslog(3)
or to the
\fBsudo\fR
log file.
The
@ -400,7 +402,7 @@ This will be addressed in a future version of
\fBsudoreplay\fR
versions 1.8.4 and higher support a flexible debugging framework
that is configured via
\fRDebug\fR
\fIDebug\fR
lines in the
sudo.conf(@mansectform@)
file.

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd February 16, 2022
.Dd September 13, 2022
.Dt SUDOREPLAY @mansectsu@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -48,7 +48,7 @@ The
.Em ID
should either be a six character sequence of digits and
upper case letters, e.g.,
.Li 0100A5
.Dq 0100A5
or a path name.
The
.Em ID
@ -74,8 +74,10 @@ with
enabled in the
.Em sudoers
file, a
.Li TSID=ID
string is logged via syslog or to the
.Dq TSID=ID
string is logged via
.Xr syslog 3
or to the
.Nm sudo
log file.
The
@ -363,7 +365,7 @@ This will be addressed in a future version of
.Nm
versions 1.8.4 and higher support a flexible debugging framework
that is configured via
.Li Debug
.Em Debug
lines in the
.Xr sudo.conf @mansectform@
file.

View File

@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.TH "VISUDO" "@mansectsu@" "April 23, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.TH "VISUDO" "@mansectsu@" "October 4, 2022" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
@ -30,7 +30,7 @@
.SH "SYNOPSIS"
.HP 7n
\fBvisudo\fR
[\fB\-chOPqsV\fR]
[\fB\-chIOPqsV\fR]
[[\fB\-f\fR]\ \fIsudoers\fR]
.SH "DESCRIPTION"
\fBvisudo\fR
@ -208,6 +208,24 @@ option.
\fB\-h\fR, \fB\--help\fR
Display a short help message to the standard output and exit.
.TP 12n
\fB\-I\fR, \fB\--no-includes\fR
Disable the editing of include files unless there is a pre-existing
syntax error.
By default,
\fBvisudo\fR
will edit the main
\fIsudoers\fR
file and any files included via
\fI@include\fR
or
\fI#include\fR
directives.
Files included via
\fI@includedir\fR
or
\fI#includedir\fR
are never edited unless they contain a syntax error.
.TP 12n
\fB\-O\fR, \fB\--owner\fR
Enforce the default ownership (user and group) of the
\fIsudoers\fR
@ -289,7 +307,7 @@ include file for syntax errors.
\fBvisudo\fR
versions 1.8.4 and higher support a flexible debugging framework
that is configured via
\fRDebug\fR
\fIDebug\fR
lines in the
sudo.conf(@mansectform@)
file.
@ -450,7 +468,7 @@ file.
The
\fIsudoers\fR
file contains a
\fRDefaults\fR
\fIDefaults\fR
setting not recognized by
\fBvisudo\fR.
.SH "SEE ALSO"

View File

@ -20,7 +20,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.Dd April 23, 2022
.Dd October 4, 2022
.Dt VISUDO @mansectsu@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -28,7 +28,7 @@
.Nd edit the sudoers file
.Sh SYNOPSIS
.Nm visudo
.Op Fl chOPqsV
.Op Fl chIOPqsV
.Op Bo Fl f Bc Ar sudoers
.Sh DESCRIPTION
.Nm
@ -203,6 +203,23 @@ path can be specified without using the
option.
.It Fl h , -help
Display a short help message to the standard output and exit.
.It Fl I , -no-includes
Disable the editing of include files unless there is a pre-existing
syntax error.
By default,
.Nm
will edit the main
.Ar sudoers
file and any files included via
.Em @include
or
.Em #include
directives.
Files included via
.Em @includedir
or
.Em #includedir
are never edited unless they contain a syntax error.
.It Fl O , -owner
Enforce the default ownership (user and group) of the
.Em sudoers
@ -281,7 +298,7 @@ include file for syntax errors.
.Nm
versions 1.8.4 and higher support a flexible debugging framework
that is configured via
.Li Debug
.Em Debug
lines in the
.Xr sudo.conf @mansectform@
file.
@ -430,7 +447,7 @@ file.
The
.Em sudoers
file contains a
.Li Defaults
.Em Defaults
setting not recognized by
.Nm .
.El

View File

@ -10,7 +10,7 @@
(TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
(TAG_SET((nt).send_mail) && (nt).send_mail != (ot).send_mail))
sv sw ta te tg th tr uk ur vi wa wo zh_CN zh_HK
if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", keywords,
if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", (char **)keywords,
$ans = <STDIN>;
if ($ans =~ /^[yY]/) {
.nr BA @BAMAN@

View File

@ -1,4 +1,3 @@
Ois
SOM
VAS
alloced
@ -8,8 +7,10 @@ ist
numer
pleas
sav
statics
thur
toke
vas
wit
statics
siz
clen

View File

@ -72,6 +72,7 @@ struct InterceptHello
/*
* Sudo response to an InterceptHello from sudo_intercept.so.
* The client uses the port number and token to connect back to sudo.
* If log_only is set there is no InterceptResponse to a PolicyCheckRequest.
*/
struct HelloResponse
{
@ -79,10 +80,11 @@ struct HelloResponse
uint64_t token_lo;
uint64_t token_hi;
int32_t portno;
protobuf_c_boolean log_only;
};
#define HELLO_RESPONSE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&hello_response__descriptor) \
, 0, 0, 0 }
, 0, 0, 0, 0 }
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2018, Dave Benson and the protobuf-c authors.
* Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -794,13 +794,13 @@ protobuf_c_version_number(void);
* The version of the protobuf-c headers, represented as a string using the same
* format as protobuf_c_version().
*/
#define PROTOBUF_C_VERSION "1.4.0"
#define PROTOBUF_C_VERSION "1.4.1"
/**
* The version of the protobuf-c headers, represented as an integer using the
* same format as protobuf_c_version_number().
*/
#define PROTOBUF_C_VERSION_NUMBER 1004000
#define PROTOBUF_C_VERSION_NUMBER 1004001
/**
* The minimum protoc-c version which works with the current version of the

View File

@ -37,45 +37,6 @@
* Macros and functions that may be missing on some operating systems.
*/
#ifndef __GNUC_PREREQ__
# ifdef __GNUC__
# define __GNUC_PREREQ__(ma, mi) \
((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
# else
# define __GNUC_PREREQ__(ma, mi) 0
# endif
#endif
/* Define away __attribute__ for non-gcc or old gcc */
#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5)
# define __attribute__(x)
#endif
/* For catching format string mismatches */
#ifndef __printflike
# if __GNUC_PREREQ__(3, 3)
# define __printflike(f, v) __attribute__((__format__ (__printf__, f, v))) __attribute__((__nonnull__ (f)))
# elif __GNUC_PREREQ__(2, 7)
# define __printflike(f, v) __attribute__((__format__ (__printf__, f, v)))
# else
# define __printflike(f, v)
# endif
#endif
#ifndef __printf0like
# if __GNUC_PREREQ__(2, 7)
# define __printf0like(f, v) __attribute__((__format__ (__printf__, f, v)))
# else
# define __printf0like(f, v)
# endif
#endif
#ifndef __format_arg
# if __GNUC_PREREQ__(2, 7)
# define __format_arg(f) __attribute__((__format_arg__ (f)))
# else
# define __format_arg(f)
# endif
#endif
#ifdef HAVE_FALLTHROUGH_ATTRIBUTE
# define FALLTHROUGH __attribute__((__fallthrough__))
#else
@ -484,22 +445,22 @@ sudo_dso_public int sudo_futimens(int fd, const struct timespec *times);
# define futimens(_a, _b) sudo_futimens((_a), (_b))
#endif /* HAVE_FUTIMENS */
#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
sudo_dso_public int sudo_snprintf(char *str, size_t n, char const *fmt, ...) __printflike(3, 4);
sudo_dso_public int sudo_snprintf(char *str, size_t n, char const *fmt, ...) sudo_printflike(3, 4);
# undef snprintf
# define snprintf sudo_snprintf
#endif /* HAVE_SNPRINTF */
#if !defined(HAVE_VSNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
sudo_dso_public int sudo_vsnprintf(char *str, size_t n, const char *fmt, va_list ap) __printflike(3, 0);
sudo_dso_public int sudo_vsnprintf(char *str, size_t n, const char *fmt, va_list ap) sudo_printflike(3, 0);
# undef vsnprintf
# define vsnprintf sudo_vsnprintf
#endif /* HAVE_VSNPRINTF */
#if !defined(HAVE_ASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
sudo_dso_public int sudo_asprintf(char **str, char const *fmt, ...) __printflike(2, 3);
sudo_dso_public int sudo_asprintf(char **str, char const *fmt, ...) sudo_printflike(2, 3);
# undef asprintf
# define asprintf sudo_asprintf
#endif /* HAVE_ASPRINTF */
#if !defined(HAVE_VASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
sudo_dso_public int sudo_vasprintf(char **str, const char *fmt, va_list ap) __printflike(2, 0);
sudo_dso_public int sudo_vasprintf(char **str, const char *fmt, va_list ap) sudo_printflike(2, 0);
# undef vasprintf
# define vasprintf sudo_vasprintf
#endif /* HAVE_VASPRINTF */
@ -523,6 +484,11 @@ sudo_dso_public size_t sudo_strnlen(const char *str, size_t maxlen);
# undef strnlen
# define strnlen(_a, _b) sudo_strnlen((_a), (_b))
#endif /* HAVE_STRNLEN */
#ifndef HAVE_FCHOWNAT
sudo_dso_public int sudo_fchownat(int dfd, const char *path, uid_t uid, gid_t gid, int flag);
# undef fchownat
# define fchownat(_a, _b, _c, _d, _e) sudo_fchownat((_a), (_b), (_c), (_d), (_e))
#endif /* HAVE_FCHOWNAT */
#ifndef HAVE_MEMRCHR
sudo_dso_public void *sudo_memrchr(const void *s, int c, size_t n);
# undef memrchr
@ -533,14 +499,30 @@ sudo_dso_public int sudo_mkdirat(int dfd, const char *path, mode_t mode);
# undef mkdirat
# define mkdirat(_a, _b, _c) sudo_mkdirat((_a), (_b), (_c))
#endif /* HAVE_MKDIRAT */
#if !defined(HAVE_MKDTEMP) || !defined(HAVE_MKSTEMPS)
#if !defined(HAVE_MKDTEMPAT) || !defined(HAVE_MKOSTEMPSAT)
# if defined(HAVE_MKDTEMPAT_NP) && defined(HAVE_MKOSTEMPSAT_NP)
# undef mkdtempat
# define mkdtempat mkdtempat_np
# undef mkostempsat
# define mkostempsat mkostempsat_np
# else
sudo_dso_public char *sudo_mkdtemp(char *path);
# undef mkdtemp
# define mkdtemp(_a) sudo_mkdtemp((_a))
# undef mkdtemp
# define mkdtemp(_a) sudo_mkdtemp((_a))
sudo_dso_public char *sudo_mkdtempat(int dfd, char *path);
# undef mkdtempat
# define mkdtempat(_a, _b) sudo_mkdtempat((_a), (_b))
sudo_dso_public int sudo_mkostempsat(int dfd, char *path, int slen, int flags);
# undef mkostempsat
# define mkostempsat(_a, _b, _c, _d) sudo_mkostempsat((_a), (_b), (_c), (_d))
sudo_dso_public int sudo_mkstemp(char *path);
# undef mkstemp
# define mkstemp(_a) sudo_mkstemp((_a))
sudo_dso_public int sudo_mkstemps(char *path, int slen);
# undef mkstemps
# define mkstemps(_a, _b) sudo_mkstemps((_a), (_b))
#endif /* !HAVE_MKDTEMP || !HAVE_MKSTEMPS */
# undef mkstemps
# define mkstemps(_a, _b) sudo_mkstemps((_a), (_b))
# endif /* HAVE_MKDTEMPAT_NP || HAVE_MKOSTEMPSAT_NP */
#endif /* !HAVE_MKDTEMPAT || !HAVE_MKOSTEMPSAT */
#ifndef HAVE_NANOSLEEP
sudo_dso_public int sudo_nanosleep(const struct timespec *timeout, struct timespec *remainder);
#undef nanosleep

View File

@ -265,13 +265,13 @@ sudo_dso_public int sudo_debug_get_active_instance_v1(void);
sudo_dso_public int sudo_debug_get_fds_v1(unsigned char **fds);
sudo_dso_public int sudo_debug_get_instance_v1(const char *program);
sudo_dso_public int sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files, const char *entry);
sudo_dso_public void sudo_debug_printf2_v1(const char *func, const char *file, int line, int level, const char *fmt, ...) __printf0like(5, 6);
sudo_dso_public void sudo_debug_printf_nvm_v1(int pri, const char *fmt, ...) __printf0like(2, 3);
sudo_dso_public void sudo_debug_printf2_v1(const char *func, const char *file, int line, int level, const char *fmt, ...) sudo_printf0like(5, 6);
sudo_dso_public void sudo_debug_printf_nvm_v1(int pri, const char *fmt, ...) sudo_printf0like(2, 3);
sudo_dso_public int sudo_debug_register_v1(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files);
sudo_dso_public int sudo_debug_register_v2(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files, int minfd);
sudo_dso_public int sudo_debug_set_active_instance_v1(int inst);
sudo_dso_public void sudo_debug_update_fd_v1(int ofd, int nfd);
sudo_dso_public void sudo_debug_vprintf2_v1(const char *func, const char *file, int line, int level, const char *fmt, va_list ap) __printf0like(5, 0);
sudo_dso_public void sudo_debug_vprintf2_v1(const char *func, const char *file, int line, int level, const char *fmt, va_list ap) sudo_printf0like(5, 0);
sudo_dso_public void sudo_debug_write2_v1(int fd, const char *func, const char *file, int line, const char *str, int len, int errnum);
sudo_dso_public bool sudo_debug_needed_v1(int level);

View File

@ -192,6 +192,9 @@ sudo_dso_public bool sudo_ev_got_break_v1(struct sudo_event_base *base);
/* Return the base an event is associated with or NULL. */
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
/* Set the base an event is associated with. */
#define sudo_ev_set_base(_ev, _b) ((_ev)->base = (_b))
/* Magic pointer value to use self pointer as callback arg. */
#define sudo_ev_self_cbarg() ((void *)-1)

View File

@ -132,7 +132,7 @@ bool eventlog_accept(const struct eventlog *evlog, int flags, eventlog_json_call
bool eventlog_exit(const struct eventlog *evlog, int flags);
bool eventlog_alert(const struct eventlog *evlog, int flags, struct timespec *alert_time, const char *reason, const char *errstr);
bool eventlog_reject(const struct eventlog *evlog, int flags, const char *reason, eventlog_json_callback_t info_cb, void *info);
bool eventlog_store_json(struct json_container *json, const struct eventlog *evlog);
bool eventlog_store_json(struct json_container *jsonc, const struct eventlog *evlog);
size_t eventlog_writeln(FILE *fp, char *line, size_t len, size_t maxlen);
void eventlog_free(struct eventlog *evlog);
void eventlog_set_type(int type);

View File

@ -164,20 +164,20 @@ typedef bool (*sudo_warn_setlocale_t)(bool, int *);
sudo_dso_public int sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func);
sudo_dso_public int sudo_fatal_callback_register_v1(sudo_fatal_callback_t func);
sudo_dso_public char *sudo_warn_gettext_v1(const char *domainname, const char *msgid) __format_arg(2);
sudo_dso_public char *sudo_warn_gettext_v1(const char *domainname, const char *msgid) sudo_attr_fmt_arg(2);
sudo_dso_public void sudo_warn_set_locale_func_v1(sudo_warn_setlocale_t func);
sudo_dso_public void sudo_fatal_nodebug_v1(const char *fmt, ...) __printf0like(1, 2) __attribute__((__noreturn__));
sudo_dso_public void sudo_fatalx_nodebug_v1(const char *fmt, ...) __printflike(1, 2) __attribute__((__noreturn__));
sudo_dso_public void sudo_gai_fatal_nodebug_v1(int errnum, const char *fmt, ...) __printflike(2, 3) __attribute__((__noreturn__));
sudo_dso_public void sudo_vfatal_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0) __attribute__((__noreturn__));
sudo_dso_public void sudo_vfatalx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0) __attribute__((__noreturn__));
sudo_dso_public void sudo_gai_vfatal_nodebug_v1(int errnum, const char *fmt, va_list ap) __printflike(2, 0) __attribute__((__noreturn__));
sudo_dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) __printf0like(1, 2);
sudo_dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) __printflike(1, 2);
sudo_dso_public void sudo_gai_warn_nodebug_v1(int errnum, const char *fmt, ...) __printflike(2, 3);
sudo_dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0);
sudo_dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0);
sudo_dso_public void sudo_gai_vwarn_nodebug_v1(int errnum, const char *fmt, va_list ap) __printflike(2, 0);
sudo_dso_public sudo_noreturn void sudo_fatal_nodebug_v1(const char *fmt, ...) sudo_printf0like(1, 2);
sudo_dso_public sudo_noreturn void sudo_fatalx_nodebug_v1(const char *fmt, ...) sudo_printflike(1, 2);
sudo_dso_public sudo_noreturn void sudo_gai_fatal_nodebug_v1(int errnum, const char *fmt, ...) sudo_printflike(2, 3);
sudo_dso_public sudo_noreturn void sudo_vfatal_nodebug_v1(const char *fmt, va_list ap) sudo_printf0like(1, 0);
sudo_dso_public sudo_noreturn void sudo_vfatalx_nodebug_v1(const char *fmt, va_list ap) sudo_printflike(1, 0);
sudo_dso_public sudo_noreturn void sudo_gai_vfatal_nodebug_v1(int errnum, const char *fmt, va_list ap) sudo_printflike(2, 0);
sudo_dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) sudo_printf0like(1, 2);
sudo_dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) sudo_printflike(1, 2);
sudo_dso_public void sudo_gai_warn_nodebug_v1(int errnum, const char *fmt, ...) sudo_printflike(2, 3);
sudo_dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) sudo_printf0like(1, 0);
sudo_dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) sudo_printflike(1, 0);
sudo_dso_public void sudo_gai_vwarn_nodebug_v1(int errnum, const char *fmt, va_list ap) sudo_printflike(2, 0);
sudo_dso_public void sudo_warn_set_conversation_v1(sudo_conv_t conv);
#define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a))

View File

@ -95,7 +95,7 @@ struct iolog_path_escape {
};
/* host_port.c */
bool iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp, char *defport, char *defport_tls);
bool iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp, const char *defport, const char *defport_tls);
/* iolog_path.c */
bool expand_iolog_path(const char *inpath, char *path, size_t pathlen, const struct iolog_path_escape *escapes, void *closure);
@ -143,10 +143,10 @@ void iolog_set_maxseq(unsigned int maxval);
void iolog_set_mode(mode_t mode);
void iolog_set_owner(uid_t uid, uid_t gid);
bool iolog_swapids(bool restore);
bool iolog_mkdirs(char *path);
bool iolog_mkdirs(const char *path);
/* iolog_filter.c */
void *iolog_pwfilt_alloc();
void *iolog_pwfilt_alloc(void);
bool iolog_pwfilt_add(void *handle, const char *pattern);
void iolog_pwfilt_free(void *handle);
bool iolog_pwfilt_remove(void *handle, const char *pattern);

View File

@ -65,34 +65,34 @@ struct json_container {
bool need_comma;
};
sudo_dso_public bool sudo_json_init_v1(struct json_container *json, int indent, bool minimal, bool memfatal);
sudo_dso_public bool sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal, bool memfatal);
#define sudo_json_init(_a, _b, _c, _d) sudo_json_init_v1((_a), (_b), (_c), (_d))
sudo_dso_public void sudo_json_free_v1(struct json_container *json);
sudo_dso_public void sudo_json_free_v1(struct json_container *jsonc);
#define sudo_json_free(_a) sudo_json_free_v1((_a))
sudo_dso_public bool sudo_json_open_object_v1(struct json_container *json, const char *name);
sudo_dso_public bool sudo_json_open_object_v1(struct json_container *jsonc, const char *name);
#define sudo_json_open_object(_a, _b) sudo_json_open_object_v1((_a), (_b))
sudo_dso_public bool sudo_json_close_object_v1(struct json_container *json);
sudo_dso_public bool sudo_json_close_object_v1(struct json_container *jsonc);
#define sudo_json_close_object(_a) sudo_json_close_object_v1((_a))
sudo_dso_public bool sudo_json_open_array_v1(struct json_container *json, const char *name);
sudo_dso_public bool sudo_json_open_array_v1(struct json_container *jsonc, const char *name);
#define sudo_json_open_array(_a, _b) sudo_json_open_array_v1((_a), (_b))
sudo_dso_public bool sudo_json_close_array_v1(struct json_container *json);
sudo_dso_public bool sudo_json_close_array_v1(struct json_container *jsonc);
#define sudo_json_close_array(_a) sudo_json_close_array_v1((_a))
sudo_dso_public bool sudo_json_add_value_v1(struct json_container *json, const char *name, struct json_value *value);
sudo_dso_public bool sudo_json_add_value_v1(struct json_container *jsonc, const char *name, struct json_value *value);
#define sudo_json_add_value(_a, _b, _c) sudo_json_add_value_v1((_a), (_b), (_c))
sudo_dso_public bool sudo_json_add_value_as_object_v1(struct json_container *json, const char *name, struct json_value *value);
sudo_dso_public bool sudo_json_add_value_as_object_v1(struct json_container *jsonc, const char *name, struct json_value *value);
#define sudo_json_add_value_as_object(_a, _b, _c) sudo_json_add_value_as_object_v1((_a), (_b), (_c))
sudo_dso_public char *sudo_json_get_buf_v1(struct json_container *json);
sudo_dso_public char *sudo_json_get_buf_v1(struct json_container *jsonc);
#define sudo_json_get_buf(_a) sudo_json_get_buf_v1((_a))
sudo_dso_public unsigned int sudo_json_get_len_v1(struct json_container *json);
sudo_dso_public unsigned int sudo_json_get_len_v1(struct json_container *jsonc);
#define sudo_json_get_len(_a) sudo_json_get_len_v1((_a))
#endif /* SUDO_JSON_H */

View File

@ -38,8 +38,8 @@ typedef int (*sudo_lbuf_output_t)(const char *);
sudo_dso_public void sudo_lbuf_init_v1(struct sudo_lbuf *lbuf, sudo_lbuf_output_t output, int indent, const char *continuation, int cols);
sudo_dso_public void sudo_lbuf_destroy_v1(struct sudo_lbuf *lbuf);
sudo_dso_public bool sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char *fmt, ...) __printflike(2, 3);
sudo_dso_public bool sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char *fmt, ...) __printflike(3, 4);
sudo_dso_public bool sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char *fmt, ...) sudo_printflike(2, 3);
sudo_dso_public bool sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char *fmt, ...) sudo_printflike(3, 4);
sudo_dso_public void sudo_lbuf_print_v1(struct sudo_lbuf *lbuf);
sudo_dso_public bool sudo_lbuf_error_v1(struct sudo_lbuf *lbuf);
sudo_dso_public void sudo_lbuf_clearerr_v1(struct sudo_lbuf *lbuf);

View File

@ -21,7 +21,7 @@
/* API version major/minor */
#define SUDO_API_VERSION_MAJOR 1
#define SUDO_API_VERSION_MINOR 19
#define SUDO_API_VERSION_MINOR 20
#define SUDO_API_MKVERSION(x, y) (((x) << 16) | (y))
#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)
@ -165,7 +165,7 @@ struct policy_plugin {
unsigned int type; /* always SUDO_POLICY_PLUGIN */
unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
sudo_printf_t sudo_plugin_printf, char * const settings[],
char * const user_info[], char * const user_env[],
char * const plugin_options[], const char **errstr);
void (*close)(int exit_status, int error); /* wait status or error */
@ -174,9 +174,9 @@ struct policy_plugin {
char *env_add[], char **command_info[],
char **argv_out[], char **user_env_out[], const char **errstr);
int (*list)(int argc, char * const argv[], int verbose,
const char *list_user, const char **errstr);
const char *user, const char **errstr);
int (*validate)(const char **errstr);
void (*invalidate)(int remove);
void (*invalidate)(int rmcred);
int (*init_session)(struct passwd *pwd, char **user_env_out[],
const char **errstr);
void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook));
@ -190,7 +190,7 @@ struct io_plugin {
unsigned int type; /* always SUDO_IO_PLUGIN */
unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
sudo_printf_t sudo_plugin_printf, char * const settings[],
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[],
char * const plugin_options[], const char **errstr);
@ -223,7 +223,7 @@ struct audit_plugin {
unsigned int type; /* always SUDO_AUDIT_PLUGIN */
unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
sudo_printf_t sudo_plugin_printf, char * const settings[],
char * const user_info[], int submit_optind,
char * const submit_argv[], char * const submit_envp[],
char * const plugin_options[], const char **errstr);
@ -249,7 +249,7 @@ struct approval_plugin {
unsigned int type; /* always SUDO_APPROVAL_PLUGIN */
unsigned int version; /* always SUDO_API_VERSION */
int (*open)(unsigned int version, sudo_conv_t conversation,
sudo_printf_t sudo_printf, char * const settings[],
sudo_printf_t sudo_plugin_printf, char * const settings[],
char * const user_info[], int submit_optind,
char * const submit_argv[], char * const submit_envp[],
char * const plugin_options[], const char **errstr);
@ -279,7 +279,8 @@ struct approval_plugin {
*/
struct sudoers_group_plugin {
unsigned int version;
int (*init)(int version, sudo_printf_t sudo_printf, char *const argv[]);
int (*init)(int version, sudo_printf_t sudo_plugin_printf,
char *const argv[]);
void (*cleanup)(void);
int (*query)(const char *user, const char *group, const struct passwd *pwd);
};

View File

@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2013-2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -247,6 +247,24 @@ sudo_dso_public const char *sudo_logpri2str_v1(int num);
/* mkdir_parents.c */
sudo_dso_public bool sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
#define sudo_mkdir_parents(_a, _b, _c, _d, _e) sudo_mkdir_parents_v1((_a), (_b), (_c), (_d), (_e))
sudo_dso_public int sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
#define sudo_open_parent_dir(_a, _b, _c, _d, _e) sudo_open_parent_dir_v1((_a), (_b), (_c), (_d), (_e))
/* mmap_alloc.c */
sudo_dso_public void *sudo_mmap_alloc_v1(size_t size) sudo_malloclike;
#define sudo_mmap_alloc(_a) sudo_mmap_alloc_v1(_a)
sudo_dso_public void *sudo_mmap_allocarray_v1(size_t count, size_t size) sudo_malloclike;
#define sudo_mmap_allocarray(_a, _b) sudo_mmap_allocarray_v1((_a), (_b))
sudo_dso_public char *sudo_mmap_strdup_v1(const char *str);
#define sudo_mmap_strdup(_a) sudo_mmap_strdup_v1(_a)
sudo_dso_public void sudo_mmap_free_v1(void *ptr);
#define sudo_mmap_free(_a) sudo_mmap_free_v1(_a)
sudo_dso_public int sudo_mmap_protect_v1(void *ptr);
#define sudo_mmap_protect(_a) sudo_mmap_protect_v1(_a)
/* multiarch.c */
sudo_dso_public char *sudo_stat_multiarch_v1(const char *path, struct stat *sb);
#define sudo_stat_multiarch(_a, _b) sudo_stat_multiarch_v1((_a), (_b))
/* parseln.c */
sudo_dso_public ssize_t sudo_parseln_v1(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp);
@ -259,7 +277,7 @@ sudo_dso_public void initprogname2(const char *, const char * const *);
/* rcstr.c */
sudo_dso_public char *sudo_rcstr_dup(const char *src);
sudo_dso_public char *sudo_rcstr_alloc(size_t len);
sudo_dso_public char *sudo_rcstr_alloc(size_t len) sudo_malloclike;
sudo_dso_public char *sudo_rcstr_addref(const char *s);
sudo_dso_public void sudo_rcstr_delref(const char *s);
@ -279,10 +297,14 @@ sudo_dso_public unsigned int sudo_pow2_roundup_v1(unsigned int len);
#define SUDO_PATH_WORLD_WRITABLE -4
#define SUDO_PATH_GROUP_WRITABLE -5
struct stat;
sudo_dso_public int sudo_secure_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sbp);
sudo_dso_public int sudo_secure_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb);
#define sudo_secure_dir(_a, _b, _c, _d) sudo_secure_dir_v1((_a), (_b), (_c), (_d))
sudo_dso_public int sudo_secure_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sbp);
sudo_dso_public int sudo_secure_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb);
#define sudo_secure_file(_a, _b, _c, _d) sudo_secure_file_v1((_a), (_b), (_c), (_d))
sudo_dso_public int sudo_secure_open_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb, int *error);
#define sudo_secure_open_file(_a, _b, _c, _d, _e) sudo_secure_open_file_v1((_a), (_b), (_c), (_d), (_e))
sudo_dso_public int sudo_secure_open_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb, int *error);
#define sudo_secure_open_dir(_a, _b, _c, _d, _e) sudo_secure_open_dir_v1((_a), (_b), (_c), (_d), (_e))
/* setgroups.c */
sudo_dso_public int sudo_setgroups_v1(int ngids, const GETGROUPS_T *gids);
@ -299,6 +321,8 @@ sudo_dso_public int sudo_strtobool_v1(const char *str);
/* strtonum.c */
/* Not versioned for historical reasons. */
sudo_dso_public long long sudo_strtonum(const char *, long long, long long, const char **);
/* Not currently exported. */
long long sudo_strtonumx(const char *str, long long minval, long long maxval, char **endp, const char **errstrp);
/* strtoid.c */
sudo_dso_public id_t sudo_strtoid_v1(const char *str, const char *sep, char **endp, const char **errstr);
@ -325,6 +349,8 @@ sudo_dso_public bool sudo_term_raw_v1(int fd, int isig);
#define sudo_term_raw(_a, _b) sudo_term_raw_v1((_a), (_b))
sudo_dso_public bool sudo_term_restore_v1(int fd, bool flush);
#define sudo_term_restore(_a, _b) sudo_term_restore_v1((_a), (_b))
sudo_dso_public bool sudo_term_is_raw_v1(int fd);
#define sudo_term_is_raw(_a) sudo_term_is_raw_v1((_a))
/* ttyname_dev.c */
sudo_dso_public char *sudo_ttyname_dev_v1(dev_t tdev, char *name, size_t namelen);

View File

@ -33,6 +33,7 @@ incdir = $(top_srcdir)/include
# Compiler & tools to use
CC = @CC@
LIBTOOL = @LIBTOOL@
GREP = @GREP@
# C preprocessor flags
CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
@ -93,11 +94,6 @@ CHECK_WRAP_OBJS = check_wrap.lo logwrap.lo
all: libsudo_eventlog.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend:
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/eventlog/Makefile.in
@ -147,13 +143,16 @@ cppcheck:
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
fuzz:
check-fuzzer:
check: $(TEST_PROGS) check-fuzzer
@if test X"$(cross_compiling)" != X"yes"; then \
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \

View File

@ -349,14 +349,14 @@ closefrom_nodebug(int lowfd)
#define MAX_MAILFLAGS 63
static void __attribute__((__noreturn__))
static sudo_noreturn void
exec_mailer(int pipein)
{
const struct eventlog_config *evl_conf = eventlog_getconf();
char *last, *mflags, *p, *argv[MAX_MAILFLAGS + 1];
const char *mpath = evl_conf->mailerpath;
int i;
char * const root_envp[] = {
const char * const root_envp[] = {
"HOME=/",
"PATH=/usr/bin:/bin:/usr/sbin:/sbin",
"LOGNAME=root",
@ -409,7 +409,7 @@ exec_mailer(int pipein)
}
sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
if (evl_conf->mailuid == ROOT_UID)
execve(mpath, argv, root_envp);
execve(mpath, argv, (char **)root_envp);
else
execv(mpath, argv);
syslog(LOG_ERR, _("unable to execute %s: %m"), mpath); // -V618
@ -627,24 +627,24 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
}
static bool
json_add_timestamp(struct json_container *json, const char *name,
json_add_timestamp(struct json_container *jsonc, const char *name,
const struct timespec *ts, bool format_timestamp)
{
struct json_value json_value;
int len;
debug_decl(json_add_timestamp, SUDO_DEBUG_PLUGIN);
if (!sudo_json_open_object(json, name))
if (!sudo_json_open_object(jsonc, name))
goto oom;
json_value.type = JSON_NUMBER;
json_value.u.number = ts->tv_sec;
if (!sudo_json_add_value(json, "seconds", &json_value))
if (!sudo_json_add_value(jsonc, "seconds", &json_value))
goto oom;
json_value.type = JSON_NUMBER;
json_value.u.number = ts->tv_nsec;
if (!sudo_json_add_value(json, "nanoseconds", &json_value))
if (!sudo_json_add_value(jsonc, "nanoseconds", &json_value))
goto oom;
if (format_timestamp) {
@ -660,7 +660,7 @@ json_add_timestamp(struct json_container *json, const char *name,
if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0') {
json_value.type = JSON_STRING;
json_value.u.string = timebuf; // -V507
if (!sudo_json_add_value(json, "iso8601", &json_value))
if (!sudo_json_add_value(jsonc, "iso8601", &json_value))
goto oom;
}
}
@ -671,13 +671,13 @@ json_add_timestamp(struct json_container *json, const char *name,
if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0') {
json_value.type = JSON_STRING;
json_value.u.string = timebuf; // -V507
if (!sudo_json_add_value(json, "localtime", &json_value))
if (!sudo_json_add_value(jsonc, "localtime", &json_value))
goto oom;
}
}
}
if (!sudo_json_close_object(json))
if (!sudo_json_close_object(jsonc))
goto oom;
debug_return_bool(true);
@ -693,7 +693,7 @@ oom:
* be stored and formatted by the caller.
*/
bool
eventlog_store_json(struct json_container *json, const struct eventlog *evlog)
eventlog_store_json(struct json_container *jsonc, const struct eventlog *evlog)
{
struct json_value json_value;
size_t i;
@ -712,112 +712,112 @@ eventlog_store_json(struct json_container *json, const struct eventlog *evlog)
json_value.type = JSON_STRING;
json_value.u.string = evlog->submituser;
if (!sudo_json_add_value(json, "submituser", &json_value))
if (!sudo_json_add_value(jsonc, "submituser", &json_value))
goto oom;
if (evlog->command != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->command;
if (!sudo_json_add_value(json, "command", &json_value))
if (!sudo_json_add_value(jsonc, "command", &json_value))
goto oom;
}
if (evlog->runuser != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->runuser;
if (!sudo_json_add_value(json, "runuser", &json_value))
if (!sudo_json_add_value(jsonc, "runuser", &json_value))
goto oom;
}
if (evlog->rungroup != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->rungroup;
if (!sudo_json_add_value(json, "rungroup", &json_value))
if (!sudo_json_add_value(jsonc, "rungroup", &json_value))
goto oom;
}
if (evlog->runchroot != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->runchroot;
if (!sudo_json_add_value(json, "runchroot", &json_value))
if (!sudo_json_add_value(jsonc, "runchroot", &json_value))
goto oom;
}
if (evlog->runcwd != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->runcwd;
if (!sudo_json_add_value(json, "runcwd", &json_value))
if (!sudo_json_add_value(jsonc, "runcwd", &json_value))
goto oom;
}
if (evlog->ttyname != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->ttyname;
if (!sudo_json_add_value(json, "ttyname", &json_value))
if (!sudo_json_add_value(jsonc, "ttyname", &json_value))
goto oom;
}
if (evlog->submithost != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->submithost;
if (!sudo_json_add_value(json, "submithost", &json_value))
if (!sudo_json_add_value(jsonc, "submithost", &json_value))
goto oom;
}
if (evlog->cwd != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->cwd;
if (!sudo_json_add_value(json, "submitcwd", &json_value))
if (!sudo_json_add_value(jsonc, "submitcwd", &json_value))
goto oom;
}
if (evlog->rungroup!= NULL && evlog->rungid != (gid_t)-1) {
json_value.type = JSON_ID;
json_value.u.id = evlog->rungid;
if (!sudo_json_add_value(json, "rungid", &json_value))
if (!sudo_json_add_value(jsonc, "rungid", &json_value))
goto oom;
}
if (evlog->runuid != (uid_t)-1) {
json_value.type = JSON_ID;
json_value.u.id = evlog->runuid;
if (!sudo_json_add_value(json, "runuid", &json_value))
if (!sudo_json_add_value(jsonc, "runuid", &json_value))
goto oom;
}
json_value.type = JSON_NUMBER;
json_value.u.number = evlog->columns;
if (!sudo_json_add_value(json, "columns", &json_value))
if (!sudo_json_add_value(jsonc, "columns", &json_value))
goto oom;
json_value.type = JSON_NUMBER;
json_value.u.number = evlog->lines;
if (!sudo_json_add_value(json, "lines", &json_value))
if (!sudo_json_add_value(jsonc, "lines", &json_value))
goto oom;
if (evlog->argv != NULL) {
if (!sudo_json_open_array(json, "runargv"))
if (!sudo_json_open_array(jsonc, "runargv"))
goto oom;
for (i = 0; (cp = evlog->argv[i]) != NULL; i++) {
json_value.type = JSON_STRING;
json_value.u.string = cp;
if (!sudo_json_add_value(json, NULL, &json_value))
if (!sudo_json_add_value(jsonc, NULL, &json_value))
goto oom;
}
if (!sudo_json_close_array(json))
if (!sudo_json_close_array(jsonc))
goto oom;
}
if (evlog->envp != NULL) {
if (!sudo_json_open_array(json, "runenv"))
if (!sudo_json_open_array(jsonc, "runenv"))
goto oom;
for (i = 0; (cp = evlog->envp[i]) != NULL; i++) {
json_value.type = JSON_STRING;
json_value.u.string = cp;
if (!sudo_json_add_value(json, NULL, &json_value))
if (!sudo_json_add_value(jsonc, NULL, &json_value))
goto oom;
}
if (!sudo_json_close_array(json))
if (!sudo_json_close_array(jsonc))
goto oom;
}
@ -829,9 +829,9 @@ oom:
}
static bool
default_json_cb(struct json_container *json, void *v)
default_json_cb(struct json_container *jsonc, void *v)
{
return eventlog_store_json(json, v);
return eventlog_store_json(jsonc, v);
}
static char *
@ -840,7 +840,7 @@ format_json(int event_type, struct eventlog_args *args,
{
eventlog_json_callback_t info_cb = args->json_info_cb;
void *info = args->json_info;
struct json_container json = { 0 };
struct json_container jsonc = { 0 };
struct json_value json_value;
const char *time_str, *type_str;
struct timespec now;
@ -880,15 +880,15 @@ format_json(int event_type, struct eventlog_args *args,
debug_return_str(NULL);
}
if (!sudo_json_init(&json, 4, compact, false))
if (!sudo_json_init(&jsonc, 4, compact, false))
goto bad;
if (!sudo_json_open_object(&json, type_str))
if (!sudo_json_open_object(&jsonc, type_str))
goto bad;
if (evlog != NULL && evlog->uuid_str[0] != '\0') {
json_value.type = JSON_STRING;
json_value.u.string = evlog->uuid_str;
if (!sudo_json_add_value(&json, "uuid", &json_value))
if (!sudo_json_add_value(&jsonc, "uuid", &json_value))
goto bad;
}
@ -907,7 +907,7 @@ format_json(int event_type, struct eventlog_args *args,
}
json_value.type = JSON_STRING;
json_value.u.string = ereason ? ereason : args->reason;
if (!sudo_json_add_value(&json, "reason", &json_value)) {
if (!sudo_json_add_value(&jsonc, "reason", &json_value)) {
free(ereason);
goto bad;
}
@ -915,7 +915,7 @@ format_json(int event_type, struct eventlog_args *args,
}
/* Log event time on server (set earlier) */
if (!json_add_timestamp(&json, "server_time", &now, true)) {
if (!json_add_timestamp(&jsonc, "server_time", &now, true)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable format timestamp");
goto bad;
@ -923,7 +923,7 @@ format_json(int event_type, struct eventlog_args *args,
/* Log event time from client */
if (args->event_time != NULL) {
if (!json_add_timestamp(&json, time_str, args->event_time, true)) {
if (!json_add_timestamp(&jsonc, time_str, args->event_time, true)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable format timestamp");
goto bad;
@ -938,7 +938,7 @@ format_json(int event_type, struct eventlog_args *args,
}
if (sudo_timespecisset(&evlog->run_time)) {
if (!json_add_timestamp(&json, "run_time", &evlog->run_time, false)) {
if (!json_add_timestamp(&jsonc, "run_time", &evlog->run_time, false)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable format timestamp");
goto bad;
@ -947,17 +947,17 @@ format_json(int event_type, struct eventlog_args *args,
if (evlog->signal_name != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->signal_name;
if (!sudo_json_add_value(&json, "signal", &json_value))
if (!sudo_json_add_value(&jsonc, "signal", &json_value))
goto bad;
json_value.type = JSON_BOOL;
json_value.u.boolean = evlog->dumped_core;
if (!sudo_json_add_value(&json, "dumped_core", &json_value))
if (!sudo_json_add_value(&jsonc, "dumped_core", &json_value))
goto bad;
}
json_value.type = JSON_NUMBER;
json_value.u.number = evlog->exit_value;
if (!sudo_json_add_value(&json, "exit_value", &json_value))
if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
goto bad;
}
@ -966,18 +966,18 @@ format_json(int event_type, struct eventlog_args *args,
if (evlog->peeraddr != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->peeraddr;
if (!sudo_json_add_value(&json, "peeraddr", &json_value))
if (!sudo_json_add_value(&jsonc, "peeraddr", &json_value))
goto bad;
}
if (evlog->iolog_path != NULL) {
json_value.type = JSON_STRING;
json_value.u.string = evlog->iolog_path;
if (!sudo_json_add_value(&json, "iolog_path", &json_value))
if (!sudo_json_add_value(&jsonc, "iolog_path", &json_value))
goto bad;
if (sudo_timespecisset(&evlog->iolog_offset)) {
if (!json_add_timestamp(&json, "iolog_offset", &evlog->iolog_offset, false)) {
if (!json_add_timestamp(&jsonc, "iolog_offset", &evlog->iolog_offset, false)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable format timestamp");
goto bad;
@ -988,23 +988,23 @@ format_json(int event_type, struct eventlog_args *args,
/* Write log info. */
if (info != NULL) {
if (!info_cb(&json, info))
if (!info_cb(&jsonc, info))
goto bad;
}
if (!sudo_json_close_object(&json))
if (!sudo_json_close_object(&jsonc))
goto bad;
/* Caller is responsible for freeing the buffer. */
debug_return_str(sudo_json_get_buf(&json));
debug_return_str(sudo_json_get_buf(&jsonc));
bad:
sudo_json_free(&json);
sudo_json_free(&jsonc);
debug_return_str(NULL);
}
/*
* Log a message to syslog, pre-pending the username and splitting the
* Log a message to syslog, prepending the username and splitting the
* message into parts if it is longer than syslog_maxlen.
*/
static bool

View File

@ -35,7 +35,7 @@
size_t
eventlog_writeln(FILE *fp, char *line, size_t linelen, size_t maxlen)
{
char *indent = "";
const char *indent = "";
char *beg = line;
char *end;
int len;

View File

@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#define SUDO_ERROR_WRAP 0

View File

@ -88,11 +88,6 @@ POBJS = $(IOBJS:.i=.plog)
all: libsudo_fuzzstub.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend:
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/fuzzstub/Makefile.in
@ -139,6 +134,9 @@ cppcheck:
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
fuzz:
check-fuzzer:

View File

@ -35,6 +35,7 @@ cross_compiling = @CROSS_COMPILING@
CC = @CC@
LIBTOOL = @LIBTOOL@
SHA1SUM = @SHA1SUM@
GREP = @GREP@
SED = @SED@
# Libraries
@ -140,11 +141,6 @@ FUZZ_IOLOG_TIMING_CORPUS = $(srcdir)/regress/corpus/seed/timing/timing.*
all: libsudo_iolog.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend:
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/iolog/Makefile.in
@ -204,7 +200,7 @@ fuzz_iolog_json_seed_corpus.zip:
rm -rf $$tdir
run-fuzz_iolog_json: fuzz_iolog_json
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -231,7 +227,7 @@ fuzz_iolog_legacy_seed_corpus.zip:
rm -rf $$tdir
run-fuzz_iolog_legacy: fuzz_iolog_legacy
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -258,7 +254,7 @@ fuzz_iolog_timing_seed_corpus.zip:
rm -rf $$tdir
run-fuzz_iolog_timing: fuzz_iolog_timing
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -305,11 +301,14 @@ cppcheck:
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
fuzz: run-fuzz_iolog_json run-fuzz_iolog_legacy run-fuzz_iolog_timing
check-fuzzer: $(FUZZ_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -328,7 +327,7 @@ check-fuzzer: $(FUZZ_PROGS)
check: $(TEST_PROGS) check-fuzzer
@if test X"$(cross_compiling)" != X"yes"; then \
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -498,13 +497,15 @@ fuzz_iolog_timing.plog: fuzz_iolog_timing.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_iolog_timing.c --i-file $< --output-file $@
host_port.lo: $(srcdir)/host_port.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/host_port.c
host_port.i: $(srcdir)/host_port.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
host_port.plog: host_port.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/host_port.c --i-file $< --output-file $@

View File

@ -16,7 +16,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
@ -30,6 +35,7 @@
#include "sudo_debug.h"
#include "sudo_gettext.h"
#include "sudo_util.h"
#include "sudo_iolog.h"
/*
* Parse a string in the form host[:port] where host can also be
@ -38,7 +44,7 @@
*/
bool
iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp,
char *defport, char *defport_tls)
const char *defport, const char *defport_tls)
{
char *flags, *port, *host = str;
bool ret = false;
@ -87,7 +93,7 @@ iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp,
}
if (port == NULL)
port = tls ? defport_tls : defport;
port = tls ? (char *)defport_tls : (char *)defport;
else if (*port == '\0')
goto done;

View File

@ -19,7 +19,7 @@
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include "config.h"
#include <config.h>
#if defined(HAVE_OPENSSL)
# if defined(HAVE_WOLFSSL)
@ -188,7 +188,7 @@ matches_common_name(const char *hostname, const char *ipaddr, const X509 *cert,
{
X509_NAME_ENTRY *common_name_entry = NULL;
ASN1_STRING *common_name_asn1 = NULL;
int common_name_loc = -1;
int common_name_loc;
debug_decl(matches_common_name, SUDO_DEBUG_UTIL);
/* Find the position of the CN field in the Subject field of the certificate */
@ -268,7 +268,7 @@ matches_subject_alternative_name(const char *hostname, const char *ipaddr, const
{
HostnameValidationResult result = MatchNotFound;
int i;
int san_names_nb = -1;
int san_names_nb;
STACK_OF(GENERAL_NAME) *san_names = NULL;
debug_decl(matches_subject_alternative_name, SUDO_DEBUG_UTIL);

View File

@ -153,34 +153,34 @@ iolog_write_info_file_legacy(int dfd, struct eventlog *evlog)
static bool
iolog_write_info_file_json(int dfd, struct eventlog *evlog)
{
struct json_container json;
struct json_container jsonc;
struct json_value json_value;
bool ret = false;
FILE *fp = NULL;
int fd = -1;
debug_decl(iolog_write_info_file_json, SUDO_DEBUG_UTIL);
if (!sudo_json_init(&json, 4, false, false))
if (!sudo_json_init(&jsonc, 4, false, false))
debug_return_bool(false);
/* Timestamp */
if (!sudo_json_open_object(&json, "timestamp"))
if (!sudo_json_open_object(&jsonc, "timestamp"))
goto oom;
json_value.type = JSON_NUMBER;
json_value.u.number = evlog->submit_time.tv_sec;
if (!sudo_json_add_value(&json, "seconds", &json_value))
if (!sudo_json_add_value(&jsonc, "seconds", &json_value))
goto oom;
json_value.type = JSON_NUMBER;
json_value.u.number = evlog->submit_time.tv_nsec;
if (!sudo_json_add_value(&json, "nanoseconds", &json_value))
if (!sudo_json_add_value(&jsonc, "nanoseconds", &json_value))
goto oom;
if (!sudo_json_close_object(&json))
if (!sudo_json_close_object(&jsonc))
goto oom;
if (!eventlog_store_json(&json, evlog))
if (!eventlog_store_json(&jsonc, evlog))
goto done;
fd = iolog_openat(dfd, "log.json", O_CREAT|O_TRUNC|O_WRONLY);
@ -197,7 +197,7 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog)
}
fd = -1;
fprintf(fp, "{%s\n}\n", sudo_json_get_buf(&json));
fprintf(fp, "{%s\n}\n", sudo_json_get_buf(&jsonc));
fflush(fp);
if (ferror(fp)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
@ -211,7 +211,7 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog)
oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
done:
sudo_json_free(&json);
sudo_json_free(&jsonc);
if (fp != NULL)
fclose(fp);
if (fd != -1)

View File

@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -46,7 +46,7 @@
* Create directory and any parent directories as needed.
*/
bool
iolog_mkdirs(char *path)
iolog_mkdirs(const char *path)
{
const mode_t iolog_filemode = iolog_get_file_mode();
const mode_t iolog_dirmode = iolog_get_dir_mode();
@ -96,29 +96,33 @@ iolog_mkdirs(char *path)
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
ok = false;
if (dfd != -1)
close(dfd);
dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (dfd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false);
if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
dfd = sudo_open_parent_dir(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
if (dfd != -1) {
/* Create final path component. */
const char *base = sudo_basename(path);
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
if (!ok) {
if (errno == EACCES && !uid_changed) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false);
if (uid_changed)
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
}
if (!ok)
sudo_warn(U_("unable to mkdir %s"), path);
} else {
if (chown(path, iolog_uid, iolog_gid) != 0) {
if (fchownat(dfd, base, iolog_uid, iolog_gid, AT_SYMLINK_NOFOLLOW) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);

View File

@ -52,36 +52,40 @@ iolog_mkdtemp(char *path)
const mode_t iolog_dirmode = iolog_get_dir_mode();
const uid_t iolog_uid = iolog_get_uid();
const gid_t iolog_gid = iolog_get_gid();
bool ok, uid_changed = false;
bool ok = false, uid_changed = false;
mode_t omask;
int dfd;
debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL);
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (dfd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false);
if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
dfd = sudo_open_parent_dir(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
if (dfd != -1) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path);
/* We cannot retry mkdtemp() so always open as iolog user */
if (!uid_changed)
uid_changed = iolog_swapids(false);
if (mkdtemp(path) == NULL) {
if (mkdtempat(dfd, path) == NULL) {
sudo_warn(U_("unable to mkdir %s"), path);
ok = false;
} else {
if (chmod(path, iolog_dirmode) != 0) {
/* Not a fatal error, pre-existing mode is 0700. */
sudo_warn(U_("unable to change mode of %s to 0%o"),
path, (unsigned int)iolog_dirmode);
}
ok = true;
}
close(dfd);
}
umask(omask);

View File

@ -36,6 +36,8 @@
#include "iolog_json.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
static FILE *
open_data(const uint8_t *data, size_t size)
{

View File

@ -34,6 +34,8 @@
#include "sudo_plugin.h"
#include "sudo_util.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
static FILE *
open_data(const uint8_t *data, size_t size)
{

View File

@ -41,6 +41,8 @@
#include "sudo_plugin.h"
#include "sudo_util.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
static int
fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)

View File

@ -45,8 +45,8 @@ struct host_port_test {
const char *host; /* parsed host */
const char *port; /* parsed port */
bool tls; /* parsed TLS flag */
char *defport; /* default port */
char *defport_tls; /* default port */
const char *defport; /* default port */
const char *defport_tls; /* default port */
bool ret; /* return value */
};

View File

@ -34,8 +34,8 @@
sudo_dso_public int main(int argc, char *argv[]);
bool
json_print_object(struct json_container *json, struct json_object *object)
static bool
json_print_object(struct json_container *jsonc, struct json_object *object)
{
struct json_item *item;
struct json_value json_value;
@ -46,40 +46,40 @@ json_print_object(struct json_container *json, struct json_object *object)
case JSON_STRING:
json_value.type = JSON_STRING;
json_value.u.string = item->u.string;
if (!sudo_json_add_value(json, item->name, &json_value))
if (!sudo_json_add_value(jsonc, item->name, &json_value))
goto oom;
break;
case JSON_NUMBER:
json_value.type = JSON_NUMBER;
json_value.u.number = item->u.number;
if (!sudo_json_add_value(json, item->name, &json_value))
if (!sudo_json_add_value(jsonc, item->name, &json_value))
goto oom;
break;
case JSON_OBJECT:
if (!sudo_json_open_object(json, item->name))
if (!sudo_json_open_object(jsonc, item->name))
goto oom;
if (!json_print_object(json, &item->u.child))
if (!json_print_object(jsonc, &item->u.child))
goto done;
if (!sudo_json_close_object(json))
if (!sudo_json_close_object(jsonc))
goto oom;
break;
case JSON_ARRAY:
if (!sudo_json_open_array(json, item->name))
if (!sudo_json_open_array(jsonc, item->name))
goto oom;
if (!json_print_object(json, &item->u.child))
if (!json_print_object(jsonc, &item->u.child))
goto done;
if (!sudo_json_close_array(json))
if (!sudo_json_close_array(jsonc))
goto oom;
break;
case JSON_BOOL:
json_value.type = JSON_BOOL;
json_value.u.boolean = item->u.boolean;
if (!sudo_json_add_value(json, item->name, &json_value))
if (!sudo_json_add_value(jsonc, item->name, &json_value))
goto oom;
break;
case JSON_NULL:
json_value.type = JSON_NULL;
if (!sudo_json_add_value(json, item->name, &json_value))
if (!sudo_json_add_value(jsonc, item->name, &json_value))
goto oom;
break;
default:
@ -98,7 +98,7 @@ done:
}
static bool
json_format(struct json_container *json, struct json_object *object)
json_format(struct json_container *jsonc, struct json_object *object)
{
struct json_item *item;
bool ret = false;
@ -111,7 +111,7 @@ json_format(struct json_container *json, struct json_object *object)
}
object = &item->u.child;
if (!json_print_object(json, object))
if (!json_print_object(jsonc, object))
goto done;
ret = true;
@ -129,7 +129,7 @@ usage(void)
}
static bool
compare(FILE *fp, const char *infile, struct json_container *json)
compare(FILE *fp, const char *infile, struct json_container *jsonc)
{
const char *cp;
unsigned int lineno = 0;
@ -137,7 +137,7 @@ compare(FILE *fp, const char *infile, struct json_container *json)
char *line = NULL;
ssize_t len;
cp = sudo_json_get_buf(json);
cp = sudo_json_get_buf(jsonc);
while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
lineno++;
@ -192,7 +192,7 @@ main(int argc, char *argv[])
usage();
for (i = 0; i < argc; i++) {
struct json_container json;
struct json_container jsonc;
const char *infile = argv[i];
const char *outfile = argv[i];
const char *cp;
@ -202,7 +202,7 @@ main(int argc, char *argv[])
ntests++;
if (!sudo_json_init(&json, 4, false, true)) {
if (!sudo_json_init(&jsonc, 4, false, true)) {
errors++;
continue;
}
@ -219,7 +219,7 @@ main(int argc, char *argv[])
}
/* Format as pretty-printed JSON */
if (!json_format(&json, &root)) {
if (!json_format(&jsonc, &root)) {
errors++;
goto next;
}
@ -237,18 +237,18 @@ main(int argc, char *argv[])
/* Compare output to expected output. */
rewind(outfp);
if (!compare(outfp, outfile, &json))
if (!compare(outfp, outfile, &jsonc))
errors++;
/* Write the formatted output to stdout for -c (cat) */
if (cat) {
fprintf(stdout, "{%s\n}\n", sudo_json_get_buf(&json));
fprintf(stdout, "{%s\n}\n", sudo_json_get_buf(&jsonc));
fflush(stdout);
}
next:
free_json_items(&root.items);
sudo_json_free(&json);
sudo_json_free(&jsonc);
if (infp != NULL)
fclose(infp);
if (outfp != NULL && outfp != infp)

View File

@ -66,7 +66,7 @@ int
main(int argc, char *argv[])
{
char testdir[] = "mkpath.XXXXXX";
char *rmargs[] = { "rm", "-rf", NULL, NULL };
const char *rmargs[] = { "rm", "-rf", NULL, NULL };
int ch, status, ntests = 0, errors = 0;
initprogname(argc > 0 ? argv[0] : "check_iolog_mkpath");
@ -97,7 +97,7 @@ main(int argc, char *argv[])
}
/* Clean up (avoid running via shell) */
execvp("rm", rmargs);
execvp("rm", (char **)rmargs);
wait(&status);
return errors;

View File

@ -49,7 +49,7 @@ static struct parse_delay_test {
/*
* Test iolog_parse_delay()
*/
void
static void
test_parse_delay(int *ntests, int *nerrors)
{
unsigned int i;
@ -106,7 +106,7 @@ static struct adjust_delay_test {
/*
* Test iolog_adjust_delay()
*/
void
static void
test_adjust_delay(int *ntests, int *nerrors)
{
unsigned int i;

View File

@ -86,11 +86,6 @@ GENERATED = log_server.pb-c.h log_server.pb-c.c
all: liblogsrv.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend:
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/logsrv/Makefile.in
@ -149,7 +144,9 @@ splint:
cppcheck:
cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
pvs-log-files: $(POBJS)
pvs-log-files:
pvs-studio:
fuzz:
@ -185,8 +182,5 @@ cleandir: realclean
log_server.pb-c.lo: $(srcdir)/log_server.pb-c.c $(incdir)/log_server.pb-c.h \
$(incdir)/protobuf-c/protobuf-c.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/log_server.pb-c.c
log_server.pb-c.i: $(srcdir)/log_server.pb-c.c $(incdir)/log_server.pb-c.h \
$(incdir)/protobuf-c/protobuf-c.h
$(CC) -E -o $@ $(CPPFLAGS) $<
log_server.pb-c.plog: log_server.pb-c.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/log_server.pb-c.c --i-file $< --output-file $@
log_server.pb-c.plog: $(srcdir)/log_server.pb-c.c
touch $@

View File

@ -81,11 +81,6 @@ POBJS = $(IOBJS:.i=.plog)
all: libprotobuf-c.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend:
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/protobuf-c/Makefile.in
@ -144,7 +139,9 @@ splint:
cppcheck:
cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
pvs-log-files: $(POBJS)
pvs-log-files:
pvs-studio:
fuzz:
@ -173,11 +170,11 @@ cleandir: realclean
.PHONY: clean mostlyclean distclean cleandir clobber realclean
# Autogenerated dependencies, do not modify
protobuf-c.lo: $(srcdir)/protobuf-c.c $(incdir)/protobuf-c/protobuf-c.h \
$(top_builddir)/config.h
protobuf-c.lo: $(srcdir)/protobuf-c.c $(incdir)/compat/endian.h \
$(incdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/protobuf-c.c
protobuf-c.i: $(srcdir)/protobuf-c.c $(incdir)/protobuf-c/protobuf-c.h \
$(top_builddir)/config.h
protobuf-c.i: $(srcdir)/protobuf-c.c $(incdir)/compat/endian.h \
$(incdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
protobuf-c.plog: protobuf-c.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/protobuf-c.c --i-file $< --output-file $@

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors.
* Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -2618,14 +2618,14 @@ parse_required_member(ScannedMember *scanned_member,
return FALSE;
def_mess = scanned_member->field->default_value;
if (len >= pref_len) {
if (len >= pref_len)
subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
allocator,
len - pref_len,
data + pref_len);
} else {
else
subm = NULL;
}
if (maybe_clear &&
*pmessage != NULL &&
*pmessage != def_mess)
@ -3246,6 +3246,9 @@ protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
/* allocate space for repeated fields, also check that all required fields have been set */
for (f = 0; f < desc->n_fields; f++) {
const ProtobufCFieldDescriptor *field = desc->fields + f;
if (field == NULL) {
continue;
}
if (field->label == PROTOBUF_C_LABEL_REPEATED) {
size_t siz =
sizeof_elt_in_repeated_array(field->type);

View File

@ -55,6 +55,7 @@ CPP = @CPP@
HOSTCPP = @CPP_FOR_BUILD@
LIBTOOL = @LIBTOOL@
SHA1SUM = @SHA1SUM@
GREP = @GREP@
SED = @SED@
AWK = @AWK@
@ -110,10 +111,10 @@ PVS_IGNORE = 'V707,V011,V002,V536'
PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
# Regression tests
TEST_PROGS = conf_test hltq_test parseln_test progname_test \
TEST_PROGS = conf_test hltq_test parseln_test progname_test parse_gids_test \
getgids getgrouplist_test multiarch_test open_parent_dir_test \
strsplit_test strtobool_test strtoid_test strtomode_test \
strtonum_test parse_gids_test getgids getgrouplist_test \
uuid_test @COMPAT_TEST_PROGS@
strtonum_test uuid_test @COMPAT_TEST_PROGS@
TEST_LIBS = @LIBS@
TEST_LDFLAGS = @LDFLAGS@
TEST_VERBOSE =
@ -143,11 +144,11 @@ SHELL = @SHELL@
LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
gettime.lo getgrouplist.lo gidlist.lo json.lo lbuf.lo locking.lo \
logfac.lo logpri.lo mkdir_parents.lo parseln.lo progname.lo rcstr.lo \
regex.lo roundup.lo secure_path.lo setgroups.lo strsplit.lo \
strtobool.lo strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
logfac.lo logpri.lo mkdir_parents.lo mmap_alloc.lo multiarch.lo \
parseln.lo progname.lo rcstr.lo regex.lo roundup.lo secure_path.lo \
setgroups.lo strsplit.lo strtobool.lo strtoid.lo strtomode.lo \
strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo term.lo \
ttyname_dev.lo ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
IOBJS = $(LTOBJS:.lo=.i)
@ -171,6 +172,10 @@ GLOBTEST_OBJS = globtest.lo glob.lo
GETDELIM_TEST_OBJS = getdelim_test.lo getdelim.lo
MULTIARCH_TEST_OBJS = multiarch_test.lo multiarch.lo
OPEN_PARENT_DIR_TEST_OBJS = open_parent_dir_test.lo mkdir_parents.lo
STRTOBOOL_TEST_OBJS = strtobool_test.lo strtobool.lo
STRTOMODE_TEST_OBJS = strtomode_test.lo strtomode.lo
@ -197,11 +202,6 @@ FUZZ_SUDO_CONF_CORPUS = $(srcdir)/regress/corpus/seed/sudo_conf/sudo.conf.*
all: libsudo_util.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
depend: siglist.c signame.c
$(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
--builddir=$(abs_top_builddir) lib/util/Makefile.in
@ -287,6 +287,12 @@ hltq_test: $(HLTQ_TEST_OBJS) libsudo_util.la
mktemp_test: $(MKTEMP_TEST_OBJS) libsudo_util.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MKTEMP_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
multiarch_test: $(MULTIARCH_TEST_OBJS) libsudo_util.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MULTIARCH_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
open_parent_dir_test: $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
parseln_test: $(PARSELN_TEST_OBJS) libsudo_util.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
@ -336,7 +342,7 @@ fuzz_sudo_conf_seed_corpus.zip:
rm -rf $$tdir
run-fuzz_sudo_conf: fuzz_sudo_conf
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -395,11 +401,14 @@ cppcheck:
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
fuzz: run-fuzz_sudo_conf
check-fuzzer: $(FUZZ_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -415,7 +424,7 @@ check-fuzzer: $(FUZZ_PROGS)
# Note: some regress checks are run from srcdir for consistent error messages
check: $(TEST_PROGS) check-fuzzer
@if test X"$(cross_compiling)" != X"yes"; then \
if locale -a 2>&1 | grep '^C.UTF-8$$' >/dev/null 2>&1; then \
if locale -a 2>&1 | $(GREP) '^C.UTF-8$$' >/dev/null 2>&1; then \
LC_ALL=C.UTF-8; export LC_ALL; \
else \
LC_ALL=C; export LC_ALL; \
@ -440,9 +449,9 @@ check: $(TEST_PROGS) check-fuzzer
if test -f globtest; then \
mkdir -p `$(SED) 's@/[^/]*$$@@' $(srcdir)/regress/glob/files | sort -u`; \
touch `cat $(srcdir)/regress/glob/files`; \
chmod 0755 `grep '/r[^/]*$$' $(srcdir)/regress/glob/files`; \
chmod 0444 `grep '/s[^/]*$$' $(srcdir)/regress/glob/files`; \
chmod 0711 `grep '/t[^/]*$$' $(srcdir)/regress/glob/files`; \
chmod 0755 `$(GREP) '/r[^/]*$$' $(srcdir)/regress/glob/files`; \
chmod 0444 `$(GREP) '/s[^/]*$$' $(srcdir)/regress/glob/files`; \
chmod 0711 `$(GREP) '/t[^/]*$$' $(srcdir)/regress/glob/files`; \
./globtest $(srcdir)/regress/glob/globtest.in || rval=`expr $$rval + $$?`; \
rm -rf fake; \
fi; \
@ -456,6 +465,8 @@ check: $(TEST_PROGS) check-fuzzer
./strsig_test || rval=`expr $$rval + $$?`; \
fi; \
./getgrouplist_test || rval=`expr $$rval + $$?`; \
./multiarch_test || rval=`expr $$rval + $$?`; \
./open_parent_dir_test || rval=`expr $$rval + $$?`; \
./strtobool_test || rval=`expr $$rval + $$?`; \
./strtoid_test || rval=`expr $$rval + $$?`; \
./strtomode_test || rval=`expr $$rval + $$?`; \
@ -704,6 +715,14 @@ fchmodat.i: $(srcdir)/fchmodat.c $(incdir)/sudo_compat.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
fchmodat.plog: fchmodat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fchmodat.c --i-file $< --output-file $@
fchownat.lo: $(srcdir)/fchownat.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fchownat.c
fchownat.i: $(srcdir)/fchownat.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
fchownat.plog: fchownat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fchownat.c --i-file $< --output-file $@
fnm_test.lo: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
@ -1088,6 +1107,38 @@ mktemp_test.i: $(srcdir)/regress/mktemp/mktemp_test.c \
$(CC) -E -o $@ $(CPPFLAGS) $<
mktemp_test.plog: mktemp_test.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/mktemp/mktemp_test.c --i-file $< --output-file $@
mmap_alloc.lo: $(srcdir)/mmap_alloc.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mmap_alloc.c
mmap_alloc.i: $(srcdir)/mmap_alloc.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
mmap_alloc.plog: mmap_alloc.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mmap_alloc.c --i-file $< --output-file $@
multiarch.lo: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/multiarch.c
multiarch.i: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
multiarch.plog: multiarch.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/multiarch.c --i-file $< --output-file $@
multiarch_test.lo: $(srcdir)/regress/multiarch/multiarch_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/multiarch/multiarch_test.c
multiarch_test.i: $(srcdir)/regress/multiarch/multiarch_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
multiarch_test.plog: multiarch_test.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/multiarch/multiarch_test.c --i-file $< --output-file $@
nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
@ -1098,6 +1149,20 @@ nanosleep.i: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
nanosleep.plog: nanosleep.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/nanosleep.c --i-file $< --output-file $@
open_parent_dir_test.lo: \
$(srcdir)/regress/open_parent_dir/open_parent_dir_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c
open_parent_dir_test.i: \
$(srcdir)/regress/open_parent_dir/open_parent_dir_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
open_parent_dir_test.plog: open_parent_dir_test.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c --i-file $< --output-file $@
openat.lo: $(srcdir)/openat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/openat.c
openat.i: $(srcdir)/openat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
@ -1276,10 +1341,12 @@ signame.i: signame.c
$(CC) -E -o $@ $(CPPFLAGS) $<
signame.plog: signame.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file signame.c --i-file $< --output-file $@
snprintf.lo: $(srcdir)/snprintf.c $(incdir)/sudo_compat.h \
snprintf.lo: $(srcdir)/snprintf.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/snprintf.c
snprintf.i: $(srcdir)/snprintf.c $(incdir)/sudo_compat.h \
snprintf.i: $(srcdir)/snprintf.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
snprintf.plog: snprintf.i
@ -1488,11 +1555,13 @@ sudo_debug.i: $(srcdir)/sudo_debug.c $(incdir)/compat/stdbool.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
sudo_debug.plog: sudo_debug.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_debug.c --i-file $< --output-file $@
sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
$(top_builddir)/config.h
sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_dso.c
sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
$(top_builddir)/config.h
sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
sudo_dso.plog: sudo_dso.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@

View File

@ -52,8 +52,8 @@
struct aix_limit {
int resource;
char *soft;
char *hard;
const char *soft;
const char *hard;
int factor;
};
@ -68,11 +68,11 @@ static struct aix_limit aix_limits[] = {
};
static int
aix_getlimit(char *user, char *lim, int *valp)
aix_getlimit(const char *user, const char *lim, int *valp)
{
debug_decl(aix_getlimit, SUDO_DEBUG_UTIL);
if (getuserattr(user, lim, valp, SEC_INT) != 0)
if (getuserattr((char *)user, (char *)lim, valp, SEC_INT) != 0)
debug_return_int(-1);
debug_return_int(0);
}
@ -169,7 +169,7 @@ aix_getauthregistry_v1(char *user, char *saved_registry)
sudo_warn("%s", U_("unable to open userdb"));
goto done;
}
ret = getuserattr(user, S_REGISTRY, &registry, SEC_CHAR);
ret = getuserattr(user, (char *)S_REGISTRY, &registry, SEC_CHAR);
if (ret == 0) {
/* sizeof(authdb_t) is guaranteed to be 16 */
if (strlcpy(saved_registry, registry, 16) >= 16) {

View File

@ -143,14 +143,14 @@ _rs_rekey(unsigned char *dat, size_t datlen)
}
/* immediately reinit for backtracking resistance */
_rs_init(rs_buf, KEYSZ + IVSZ);
memset(rs_buf, 0, KEYSZ + IVSZ); // -V512
memset(rs_buf, 0, KEYSZ + IVSZ); // -V::512, 1086
rs_have = sizeof(rs_buf) - KEYSZ - IVSZ;
}
static inline void
_rs_random_buf(void *_buf, size_t n)
{
unsigned char *buf = (unsigned char *)_buf;
unsigned char *buf = _buf;
unsigned char *keystream;
size_t m;

View File

@ -23,6 +23,11 @@
#include <config.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@ -33,6 +38,8 @@
#include "sudo_debug.h"
#include "sudo_digest.h"
#define SUDO_LIBGCRYPT_VERSION_MIN "1.3.0"
struct sudo_digest {
int gcry_digest_type;
unsigned int digest_len;
@ -61,9 +68,21 @@ struct sudo_digest *
sudo_digest_alloc_v1(int digest_type)
{
debug_decl(sudo_digest_alloc, SUDO_DEBUG_UTIL);
static bool initialized = false;
struct sudo_digest *dig;
int gcry_digest_type;
if (!initialized) {
if (!gcry_check_version(SUDO_LIBGCRYPT_VERSION_MIN)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"libgcrypt too old (need %s, have %s)",
SUDO_LIBGCRYPT_VERSION_MIN, gcry_check_version(NULL));
debug_return_ptr(NULL);
}
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
initialized = true;
}
gcry_digest_type = sudo_digest_type_to_gcry(digest_type);
if (gcry_digest_type == -1) {
errno = EINVAL;

View File

@ -239,7 +239,7 @@ warning(const char *errstr, const char *fmt, va_list ap)
fputs(": ", stderr);
fputs(errstr, stderr);
}
if (isatty(fileno(stderr)))
if (sudo_term_is_raw(fileno(stderr)))
putc('\r', stderr);
putc('\n', stderr);
}

67
lib/util/fchownat.c Normal file
View File

@ -0,0 +1,67 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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.
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#include <fcntl.h>
#include <unistd.h>
#include "sudo_compat.h"
#ifndef HAVE_FCHOWNAT
int
sudo_fchownat(int dfd, const char *path, uid_t uid, gid_t gid, int flags)
{
int odfd, ret;
if (dfd == AT_FDCWD) {
if (flags & AT_SYMLINK_NOFOLLOW)
return lchown(path, uid, gid);
else
return chown(path, uid, gid);
}
/* Save cwd */
if ((odfd = open(".", O_RDONLY)) == -1)
return -1;
if (fchdir(dfd) == -1) {
close(odfd);
return -1;
}
if (flags & AT_SYMLINK_NOFOLLOW)
ret = lchown(path, uid, gid);
else
ret = chown(path, uid, gid);
/* Restore cwd */
if (fchdir(odfd) == -1) {
/* Should not happen */
ret = -1;
}
close(odfd);
return ret;
}
#endif /* HAVE_FCHOWNAT */

View File

@ -20,6 +20,11 @@
* http://man.openbsd.org/getentropy.2
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#ifndef HAVE_GETENTROPY

View File

@ -238,7 +238,7 @@ str2grp(const char *instr, int inlen, void *ent, char *buf, int buflen)
/* Check for YP inclusion/exclusion entries. */
if (*cp == '+' || *cp == '-') {
/* Only the name is required for YP inclusion/exclusion entries. */
grp->gr_passwd = "";
grp->gr_passwd = (char *)"";
grp->gr_gid = 0;
grp->gr_mem = NULL;
yp = 1;

View File

@ -96,7 +96,7 @@ int optreset; /* reset getopt */
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG ""
#define EMSG (char *)""
#ifdef GNU_COMPATIBLE
#define NO_PREFIX (-1)
@ -202,7 +202,7 @@ parse_long_options(char * const *nargv, const char *options,
{
char *current_argv, *has_equal;
#ifdef GNU_COMPATIBLE
char *current_dash;
const char *current_dash;
#endif
size_t current_argv_len;
int i, match, exact_match, second_partial_match;

View File

@ -44,13 +44,13 @@
* Returns true on success, false if out of memory.
*/
static bool
json_expand_buf(struct json_container *json)
json_expand_buf(struct json_container *jsonc)
{
char *newbuf;
debug_decl(json_expand_buf, SUDO_DEBUG_UTIL);
if ((newbuf = reallocarray(json->buf, 2, json->bufsize)) == NULL) {
if (json->memfatal) {
if ((newbuf = reallocarray(jsonc->buf, 2, jsonc->bufsize)) == NULL) {
if (jsonc->memfatal) {
sudo_fatalx(U_("%s: %s"),
__func__, U_("unable to allocate memory"));
}
@ -58,8 +58,8 @@ json_expand_buf(struct json_container *json)
"%s: %s", __func__, "unable to allocate memory");
debug_return_bool(false);
}
json->buf = newbuf;
json->bufsize *= 2;
jsonc->buf = newbuf;
jsonc->bufsize *= 2;
debug_return_bool(true);
}
@ -69,24 +69,24 @@ json_expand_buf(struct json_container *json)
* Append "indent" number of blank characters.
*/
static bool
json_new_line(struct json_container *json)
json_new_line(struct json_container *jsonc)
{
int indent = json->indent_level;
int indent = jsonc->indent_level;
debug_decl(json_new_line, SUDO_DEBUG_UTIL);
/* No non-essential white space in minimal mode. */
if (json->minimal)
if (jsonc->minimal)
debug_return_bool(true);
while (json->buflen + 1 + indent >= json->bufsize) {
if (!json_expand_buf(json))
while (jsonc->buflen + 1 + indent >= jsonc->bufsize) {
if (!json_expand_buf(jsonc))
debug_return_bool(false);
}
json->buf[json->buflen++] = '\n';
jsonc->buf[jsonc->buflen++] = '\n';
while (indent--) {
json->buf[json->buflen++] = ' ';
jsonc->buf[jsonc->buflen++] = ' ';
}
json->buf[json->buflen] = '\0';
jsonc->buf[jsonc->buflen] = '\0';
debug_return_bool(true);
}
@ -96,20 +96,20 @@ json_new_line(struct json_container *json)
* Does not perform any quoting.
*/
static bool
json_append_buf(struct json_container *json, const char *str)
json_append_buf(struct json_container *jsonc, const char *str)
{
size_t len;
debug_decl(json_append_buf, SUDO_DEBUG_UTIL);
len = strlen(str);
while (json->buflen + len >= json->bufsize) {
if (!json_expand_buf(json))
while (jsonc->buflen + len >= jsonc->bufsize) {
if (!json_expand_buf(jsonc))
debug_return_bool(false);
}
memcpy(json->buf + json->buflen, str, len);
json->buflen += len;
json->buf[json->buflen] = '\0';
memcpy(jsonc->buf + jsonc->buflen, str, len);
jsonc->buflen += len;
jsonc->buf[jsonc->buflen] = '\0';
debug_return_bool(true);
}
@ -119,12 +119,12 @@ json_append_buf(struct json_container *json, const char *str)
* Does not support unicode escapes.
*/
static bool
json_append_string(struct json_container *json, const char *str)
json_append_string(struct json_container *jsonc, const char *str)
{
char ch;
debug_decl(json_append_string, SUDO_DEBUG_UTIL);
if (!json_append_buf(json, "\""))
if (!json_append_buf(jsonc, "\""))
debug_return_bool(false);
while ((ch = *str++) != '\0') {
char buf[3], *cp = buf;
@ -157,29 +157,29 @@ json_append_string(struct json_container *json, const char *str)
}
*cp++ = ch;
*cp++ = '\0';
if (!json_append_buf(json, buf))
if (!json_append_buf(jsonc, buf))
debug_return_bool(false);
}
if (!json_append_buf(json, "\""))
if (!json_append_buf(jsonc, "\""))
debug_return_bool(false);
debug_return_bool(true);
}
bool
sudo_json_init_v1(struct json_container *json, int indent, bool minimal,
sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal,
bool memfatal)
{
debug_decl(sudo_json_init, SUDO_DEBUG_UTIL);
memset(json, 0, sizeof(*json));
json->indent_level = indent;
json->indent_increment = indent;
json->minimal = minimal;
json->memfatal = memfatal;
json->buf = malloc(64 * 1024);
if (json->buf == NULL) {
if (json->memfatal) {
memset(jsonc, 0, sizeof(*jsonc));
jsonc->indent_level = indent;
jsonc->indent_increment = indent;
jsonc->minimal = minimal;
jsonc->memfatal = memfatal;
jsonc->buf = malloc(64 * 1024);
if (jsonc->buf == NULL) {
if (jsonc->memfatal) {
sudo_fatalx(U_("%s: %s"),
__func__, U_("unable to allocate memory"));
}
@ -187,162 +187,162 @@ sudo_json_init_v1(struct json_container *json, int indent, bool minimal,
"%s: %s", __func__, "unable to allocate memory");
debug_return_bool(false);
}
*json->buf = '\0';
json->bufsize = 64 * 1024;
*jsonc->buf = '\0';
jsonc->bufsize = 64 * 1024;
debug_return_bool(true);
}
void
sudo_json_free_v1(struct json_container *json)
sudo_json_free_v1(struct json_container *jsonc)
{
debug_decl(sudo_json_free, SUDO_DEBUG_UTIL);
free(json->buf);
memset(json, 0, sizeof(*json));
free(jsonc->buf);
memset(jsonc, 0, sizeof(*jsonc));
debug_return;
}
bool
sudo_json_open_object_v1(struct json_container *json, const char *name)
sudo_json_open_object_v1(struct json_container *jsonc, const char *name)
{
debug_decl(sudo_json_open_object, SUDO_DEBUG_UTIL);
/* Add comma if we are continuing an object/array. */
if (json->need_comma) {
if (!json_append_buf(json, ","))
if (jsonc->need_comma) {
if (!json_append_buf(jsonc, ","))
debug_return_bool(false);
}
if (!json_new_line(json))
if (!json_new_line(jsonc))
debug_return_bool(false);
if (name != NULL) {
json_append_string(json, name);
if (!json_append_buf(json, json->minimal ? ":{" : ": {"))
json_append_string(jsonc, name);
if (!json_append_buf(jsonc, jsonc->minimal ? ":{" : ": {"))
debug_return_bool(false);
} else {
if (!json_append_buf(json, "{"))
if (!json_append_buf(jsonc, "{"))
debug_return_bool(false);
}
json->indent_level += json->indent_increment;
json->need_comma = false;
jsonc->indent_level += jsonc->indent_increment;
jsonc->need_comma = false;
debug_return_bool(true);
}
bool
sudo_json_close_object_v1(struct json_container *json)
sudo_json_close_object_v1(struct json_container *jsonc)
{
debug_decl(sudo_json_close_object, SUDO_DEBUG_UTIL);
if (!json->minimal) {
json->indent_level -= json->indent_increment;
if (!json_new_line(json))
if (!jsonc->minimal) {
jsonc->indent_level -= jsonc->indent_increment;
if (!json_new_line(jsonc))
debug_return_bool(false);
}
if (!json_append_buf(json, "}"))
if (!json_append_buf(jsonc, "}"))
debug_return_bool(false);
debug_return_bool(true);
}
bool
sudo_json_open_array_v1(struct json_container *json, const char *name)
sudo_json_open_array_v1(struct json_container *jsonc, const char *name)
{
debug_decl(sudo_json_open_array, SUDO_DEBUG_UTIL);
/* Add comma if we are continuing an object/array. */
if (json->need_comma) {
if (!json_append_buf(json, ","))
if (jsonc->need_comma) {
if (!json_append_buf(jsonc, ","))
debug_return_bool(false);
}
if (!json_new_line(json))
if (!json_new_line(jsonc))
debug_return_bool(false);
if (name != NULL) {
json_append_string(json, name);
if (!json_append_buf(json, json->minimal ? ":[" : ": ["))
json_append_string(jsonc, name);
if (!json_append_buf(jsonc, jsonc->minimal ? ":[" : ": ["))
debug_return_bool(false);
} else {
if (!json_append_buf(json, "["))
if (!json_append_buf(jsonc, "["))
debug_return_bool(false);
}
json->indent_level += json->indent_increment;
json->need_comma = false;
jsonc->indent_level += jsonc->indent_increment;
jsonc->need_comma = false;
debug_return_bool(true);
}
bool
sudo_json_close_array_v1(struct json_container *json)
sudo_json_close_array_v1(struct json_container *jsonc)
{
debug_decl(sudo_json_close_array, SUDO_DEBUG_UTIL);
if (!json->minimal) {
json->indent_level -= json->indent_increment;
if (!json_new_line(json))
if (!jsonc->minimal) {
jsonc->indent_level -= jsonc->indent_increment;
if (!json_new_line(jsonc))
debug_return_bool(false);
}
if (!json_append_buf(json, "]"))
if (!json_append_buf(jsonc, "]"))
debug_return_bool(false);
debug_return_bool(true);
}
static bool
sudo_json_add_value_int(struct json_container *json, const char *name,
sudo_json_add_value_int(struct json_container *jsonc, const char *name,
struct json_value *value, bool as_object)
{
char numbuf[(((sizeof(long long) * 8) + 2) / 3) + 2];
debug_decl(sudo_json_add_value, SUDO_DEBUG_UTIL);
/* Add comma if we are continuing an object/array. */
if (json->need_comma) {
if (!json_append_buf(json, ","))
if (jsonc->need_comma) {
if (!json_append_buf(jsonc, ","))
debug_return_bool(false);
}
if (!json_new_line(json))
if (!json_new_line(jsonc))
debug_return_bool(false);
json->need_comma = true;
jsonc->need_comma = true;
if (as_object) {
if (!json_append_buf(json, json->minimal ? "{" : "{ "))
if (!json_append_buf(jsonc, jsonc->minimal ? "{" : "{ "))
debug_return_bool(false);
}
/* name */
if (name != NULL) {
if (!json_append_string(json, name))
if (!json_append_string(jsonc, name))
debug_return_bool(false);
if (!json_append_buf(json, json->minimal ? ":" : ": "))
if (!json_append_buf(jsonc, jsonc->minimal ? ":" : ": "))
debug_return_bool(false);
}
/* value */
switch (value->type) {
case JSON_STRING:
if (!json_append_string(json, value->u.string))
if (!json_append_string(jsonc, value->u.string))
debug_return_bool(false);
break;
case JSON_ID:
snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)value->u.id);
if (!json_append_buf(json, numbuf))
if (!json_append_buf(jsonc, numbuf))
debug_return_bool(false);
break;
case JSON_NUMBER:
snprintf(numbuf, sizeof(numbuf), "%lld", value->u.number);
if (!json_append_buf(json, numbuf))
if (!json_append_buf(jsonc, numbuf))
debug_return_bool(false);
break;
case JSON_NULL:
if (!json_append_buf(json, "null"))
if (!json_append_buf(jsonc, "null"))
debug_return_bool(false);
break;
case JSON_BOOL:
if (!json_append_buf(json, value->u.boolean ? "true" : "false"))
if (!json_append_buf(jsonc, value->u.boolean ? "true" : "false"))
debug_return_bool(false);
break;
case JSON_ARRAY:
@ -354,7 +354,7 @@ sudo_json_add_value_int(struct json_container *json, const char *name,
}
if (as_object) {
if (!json_append_buf(json, json->minimal ? "}" : " }"))
if (!json_append_buf(jsonc, jsonc->minimal ? "}" : " }"))
debug_return_bool(false);
}
@ -362,27 +362,27 @@ sudo_json_add_value_int(struct json_container *json, const char *name,
}
bool
sudo_json_add_value_v1(struct json_container *json, const char *name,
sudo_json_add_value_v1(struct json_container *jsonc, const char *name,
struct json_value *value)
{
return sudo_json_add_value_int(json, name, value, false);
return sudo_json_add_value_int(jsonc, name, value, false);
}
bool
sudo_json_add_value_as_object_v1(struct json_container *json, const char *name,
sudo_json_add_value_as_object_v1(struct json_container *jsonc, const char *name,
struct json_value *value)
{
return sudo_json_add_value_int(json, name, value, true);
return sudo_json_add_value_int(jsonc, name, value, true);
}
char *
sudo_json_get_buf_v1(struct json_container *json)
sudo_json_get_buf_v1(struct json_container *jsonc)
{
return json->buf;
return jsonc->buf;
}
unsigned int
sudo_json_get_len_v1(struct json_container *json)
sudo_json_get_len_v1(struct json_container *jsonc)
{
return json->buflen;
return jsonc->buflen;
}

View File

@ -96,7 +96,7 @@ sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char *
{
int len, saved_len = lbuf->len;
bool ret = false;
char *cp, *s;
const char *cp, *s;
va_list ap;
debug_decl(sudo_lbuf_append_quoted, SUDO_DEBUG_UTIL);
@ -155,7 +155,7 @@ sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char *fmt, ...)
int len, saved_len = lbuf->len;
bool ret = false;
va_list ap;
char *s;
const char *s;
debug_decl(sudo_lbuf_append, SUDO_DEBUG_UTIL);
if (sudo_lbuf_error(lbuf))

View File

@ -39,7 +39,7 @@
* For converting between syslog numbers and strings.
*/
struct strmap {
char *name;
const char *name;
int num;
};

View File

@ -39,7 +39,7 @@
* For converting between syslog numbers and strings.
*/
struct strmap {
char *name;
const char *name;
int num;
};

View File

@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -76,16 +76,17 @@ is_dir(int dfd, const char *name, int namelen, bool quiet)
}
/*
* Create any parent directories needed by path (but not path itself).
* Create any parent directories needed by path (but not path itself)
* and return an open fd for the parent directory or -1 on error.
*/
bool
sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet)
int
sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
bool quiet)
{
const char *cp, *ep, *pathend;
char name[PATH_MAX];
bool ret = false;
int parentfd;
debug_decl(sudo_mkdir_parents, SUDO_DEBUG_UTIL);
debug_decl(sudo_open_parent_dir, SUDO_DEBUG_UTIL);
/* Starting parent dir is either root or cwd. */
cp = path;
@ -100,25 +101,27 @@ sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool
if (parentfd == -1) {
if (!quiet)
sudo_warn(U_("unable to open %s"), *path == '/' ? "/" : ".");
debug_return_bool(false);
debug_return_int(-1);
}
/* Iterate over path components, skipping the last one. */
pathend = cp + strlen(cp);
for (cp = sudo_strsplit(cp, pathend, "/", &ep); cp != NULL && ep != NULL;
for (cp = sudo_strsplit(cp, pathend, "/", &ep); cp != NULL && *ep != '\0';
cp = sudo_strsplit(NULL, pathend, "/", &ep)) {
int dfd, len;
size_t len = (size_t)(ep - cp);
int dfd;
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %.*s, mode 0%o, uid %d, gid %d", (int)(ep - path),
path, (unsigned int)mode, (int)uid, (int)gid);
len = snprintf(name, sizeof(name), "%.*s", (int)(ep - cp), cp);
if (len >= ssizeof(name)) {
"mkdir %.*s, mode 0%o, uid %d, gid %d", (int)(ep - path), path,
(unsigned int)mode, (int)uid, (int)gid);
if (len >= sizeof(name)) {
errno = ENAMETOOLONG;
if (!quiet)
sudo_warn(U_("unable to open %.*s"), (int)(ep - path), path);
goto done;
sudo_warn(U_("unable to mkdir %.*s"), (int)(ep - path), path);
goto bad;
}
memcpy(name, cp, len);
name[len] = '\0';
reopen:
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK, 0);
if (dfd == -1) {
@ -127,7 +130,7 @@ reopen:
sudo_warn(U_("unable to open %.*s"),
(int)(ep - path), path);
}
goto done;
goto bad;
}
if (mkdirat(parentfd, name, mode) == 0) {
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0);
@ -136,12 +139,12 @@ reopen:
sudo_warn(U_("unable to open %.*s"),
(int)(ep - path), path);
}
goto done;
goto bad;
}
/* Make sure the path we created is still a directory. */
if (!is_dir(dfd, path, ep - path, quiet)) {
close(dfd);
goto done;
goto bad;
}
if (uid != (uid_t)-1 && gid != (gid_t)-1) {
if (fchown(dfd, uid, gid) != 0) {
@ -157,22 +160,40 @@ reopen:
sudo_warn(U_("unable to mkdir %.*s"),
(int)(ep - path), path);
}
goto done;
goto bad;
}
} else {
/* Already exists, make sure it is a directory. */
if (!is_dir(dfd, path, ep - path, quiet)) {
close(dfd);
goto done;
goto bad;
}
}
close(parentfd);
parentfd = dfd;
}
ret = true;
done:
debug_return_int(parentfd);
bad:
if (parentfd != -1)
close(parentfd);
debug_return_bool(ret);
debug_return_int(-1);
}
/*
* Create any parent directories needed by path (but not path itself).
* Not currently used.
*/
bool
sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
bool quiet)
{
int fd;
debug_decl(sudo_mkdir_parents, SUDO_DEBUG_UTIL);
fd = sudo_open_parent_dir(path, uid, gid, mode, quiet);
if (fd == -1)
debug_return_bool(false);
close(fd);
debug_return_bool(true);
}

View File

@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2001, 2003, 2004, 2008-2011, 2013, 2015, 2017, 2018
* Copyright (c) 2001, 2003, 2004, 2008-2011, 2013, 2015, 2017, 2018, 2022
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@ -24,7 +24,8 @@
#include <config.h>
#if !defined(HAVE_MKSTEMPS) || !defined(HAVE_MKDTEMP)
#if (!defined(HAVE_MKDTEMPAT) && !defined(HAVE_MKDTEMPAT_NP)) || \
(!defined(HAVE_MKOSTEMPSAT) && !defined(HAVE_MKOSTEMPSAT_NP))
#include <sys/stat.h>
@ -32,9 +33,7 @@
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#include <stdlib.h>
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
@ -55,12 +54,14 @@
#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
#define MIN_X 6
#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_SYNC)
static int
mktemp_internal(char *path, int slen, int mode)
mktemp_internal(int dfd, char *path, int slen, int mode, int flags)
{
char *start, *cp, *ep;
const char tempchars[] = TEMPCHARS;
unsigned int r, tries;
unsigned int tries;
size_t len;
int fd;
@ -71,31 +72,43 @@ mktemp_internal(char *path, int slen, int mode)
}
ep = path + len - slen;
tries = 1;
for (start = ep; start > path && start[-1] == 'X'; start--) {
if (tries < INT_MAX / NUM_CHARS)
tries *= NUM_CHARS;
}
tries *= 2;
for (start = ep; start > path && start[-1] == 'X'; start--)
;
if (ep - start < MIN_X) {
errno = EINVAL;
return -1;
}
if (flags & ~MKOTEMP_FLAGS) {
errno = EINVAL;
return -1;
}
flags |= O_CREAT | O_EXCL | O_RDWR;
tries = INT_MAX;
do {
for (cp = start; cp != ep; cp++) {
r = arc4random_uniform(NUM_CHARS);
*cp = tempchars[r];
}
cp = start;
do {
unsigned short rbuf[16];
unsigned int i;
/*
* Avoid lots of arc4random() calls by using
* a buffer sized for up to 16 Xs at a time.
*/
arc4random_buf(rbuf, sizeof(rbuf));
for (i = 0; i < nitems(rbuf) && cp != ep; i++)
*cp++ = tempchars[rbuf[i] % NUM_CHARS];
} while (cp != ep);
switch (mode) {
case MKTEMP_FILE:
fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
fd = openat(dfd, path, flags, S_IRUSR|S_IWUSR);
if (fd != -1 || errno != EEXIST)
return fd;
break;
case MKTEMP_DIR:
if (mkdir(path, S_IRWXU) == 0)
if (mkdirat(dfd, path, S_IRWXU) == 0)
return 0;
if (errno != EEXIST)
return -1;
@ -107,17 +120,53 @@ mktemp_internal(char *path, int slen, int mode)
return -1;
}
int
sudo_mkstemps(char *path, int slen)
{
return mktemp_internal(path, slen, MKTEMP_FILE);
}
char *
sudo_mkdtemp(char *path)
{
if (mktemp_internal(path, 0, MKTEMP_DIR) == -1)
if (mktemp_internal(AT_FDCWD, path, 0, MKTEMP_DIR, 0) == -1)
return NULL;
return path;
}
#endif /* !HAVE_MKSTEMPS || !HAVE_MKDTEMP */
char *
sudo_mkdtempat(int dfd, char *path)
{
if (mktemp_internal(dfd, path, 0, MKTEMP_DIR, 0) == -1)
return NULL;
return path;
}
int
sudo_mkostempsat(int dfd, char *path, int slen, int flags)
{
return mktemp_internal(dfd, path, slen, MKTEMP_FILE, flags);
}
#ifdef notyet
int
sudo_mkostemps(char *path, int slen, int flags)
{
return mktemp_internal(AT_FDCWD, path, slen, MKTEMP_FILE, flags);
}
#endif
int
sudo_mkstemp(char *path)
{
return mktemp_internal(AT_FDCWD, path, 0, MKTEMP_FILE, 0);
}
#ifdef notyet
int
sudo_mkostemp(char *path, int flags)
{
return mktemp_internal(AT_FDCWD, path, 0, MKTEMP_FILE, flags);
}
#endif
int
sudo_mkstemps(char *path, int slen)
{
return mktemp_internal(AT_FDCWD, path, slen, MKTEMP_FILE, 0);
}
#endif /* !HAVE_MKDTEMPAT || !HAVE_MKOSTEMPSAT */

158
lib/util/mmap_alloc.c Normal file
View File

@ -0,0 +1,158 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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.
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#endif
#include "sudo_compat.h"
#include "sudo_util.h"
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
# define MAP_ANON MAP_ANONYMOUS
#endif
#ifndef MAP_FAILED
# define MAP_FAILED ((void *)-1)
#endif
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
/*
* Allocate "size" bytes via mmap().
* Space is allocated to store the size for later unmapping.
*/
void *
sudo_mmap_alloc_v1(size_t size)
{
void *ptr;
unsigned long *ulp;
#ifndef MAP_ANON
int fd;
/* SunOS-style mmap allocation using /dev/zero. */
if ((fd = open("/dev/zero", O_RDWR)) == -1)
return NULL;
size += sizeof(unsigned long);
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
#else
size += sizeof(unsigned long);
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
#endif
if (ptr == MAP_FAILED) {
errno = ENOMEM;
return NULL;
}
/* Store size before the actual data. */
ulp = (unsigned long *)ptr;
ulp[0] = size;
return (void *)&ulp[1];
}
/*
* Allocate "nmemb" elements of "size" bytes via mmap().
* If overflow would occur, errno is set to ENOMEM and
* NULL is returned.
*/
void *
sudo_mmap_allocarray_v1(size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return sudo_mmap_alloc_v1(nmemb * size);
}
/*
* Make a copy of "str" via mmap() and return it.
*/
char *
sudo_mmap_strdup_v1(const char *str)
{
size_t len = strlen(str);
char *newstr;
if (len == SIZE_MAX) {
errno = ENOMEM;
return NULL;
}
newstr = sudo_mmap_alloc_v1(len + 1);
memcpy(newstr, str, len);
newstr[len] = '\0';
return newstr;
}
/*
* Set the page permissions for the allocation represented by "ptr" to
* read-only. Returns 0 on success, -1 on failure.
*/
int
sudo_mmap_protect_v1(void *ptr)
{
if (ptr != NULL) {
unsigned long *ulp = ptr;
const unsigned long size = ulp[-1];
return mprotect((void *)&ulp[-1], size, PROT_READ);
}
/* Can't protect NULL. */
errno = EINVAL;
return -1;
}
/*
* Free "ptr" allocated by sudo_mmap_alloc().
* The allocated size is stored (as unsigned long) in ptr[-1].
*/
void
sudo_mmap_free_v1(void *ptr)
{
if (ptr != NULL) {
unsigned long *ulp = (unsigned long *)ptr - 1;
const unsigned long size = ulp[0];
int saved_errno = errno;
(void)munmap((void *)ulp, size);
errno = saved_errno;
}
}

103
lib/util/multiarch.c Normal file
View File

@ -0,0 +1,103 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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.
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#ifdef __linux__
# include <sys/utsname.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sudo_compat.h"
#include "sudo_util.h"
# if defined(__linux__)
/*
* On Linux systems that use multi-arch, the actual DSO may be in a
* machine-specific subdirectory. If the specified path contains
* /lib/ or /libexec/, insert a multi-arch directory after it.
* If sb is non-NULL, stat(2) will be called on the new path, filling in sb.
* Returns a dynamically allocated string on success and NULL on failure.
*/
char *
sudo_stat_multiarch_v1(const char *path, struct stat *sb)
{
# if defined(__ILP32__)
const char *libdirs[] = { "/libx32/", "/lib/", "/libexec/", NULL };
# elif defined(__LP64__)
const char *libdirs[] = { "/lib64/", "/lib/", "/libexec/", NULL };
# else
const char *libdirs[] = { "/lib32/", "/lib/", "/libexec/", NULL };
# endif
const char **lp, *lib, *slash;
struct utsname unamebuf;
char *newpath = NULL;
int len;
if (uname(&unamebuf) == -1)
return NULL;
for (lp = libdirs; *lp != NULL; lp++) {
/* Replace lib64, lib32, libx32 with lib in new path. */
const char *newlib = lp == libdirs ? "/lib/" : *lp;
/* Search for lib dir in path, find the trailing slash. */
lib = strstr(path, *lp);
if (lib == NULL)
continue;
slash = lib + strlen(*lp) - 1;
/* Make sure there isn't already a machine-linux-gnu dir. */
len = strcspn(slash + 1, "/-");
if (strncmp(slash + 1 + len, "-linux-gnu/", 11) == 0) {
/* Multiarch already present. */
break;
}
/* Add machine-linux-gnu dir after /lib/ or /libexec/. */
len = asprintf(&newpath, "%.*s%s%s-linux-gnu%s",
(int)(lib - path), path, newlib, unamebuf.machine, slash);
if (len == -1) {
newpath = NULL;
break;
}
/* If sb was set, use stat(2) to make sure newpath exists. */
if (sb == NULL || stat(newpath, sb) == 0)
break;
free(newpath);
newpath = NULL;
}
return newpath;
}
#else
char *
sudo_stat_multiarch_v1(const char *path, struct stat *sb)
{
return NULL;
}
#endif /* __linux__ */

View File

@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SUDO_ERROR_WRAP 0

View File

@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_FNMATCH
# include <fnmatch.h>
#else

View File

@ -33,6 +33,8 @@
#include "sudo_plugin.h"
#include "sudo_util.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
static int
fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)

View File

@ -28,6 +28,7 @@
#endif
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include "sudo_compat.h"
#include "sudo_fatal.h"

View File

@ -15,6 +15,7 @@
# include "compat/glob.h"
#endif
#include <errno.h>
#include <unistd.h>
#include "sudo_compat.h"
#include "sudo_util.h"
@ -183,7 +184,8 @@ main(int argc, char **argv)
return errors;
}
int test_glob(struct gl_entry *entry)
static int
test_glob(struct gl_entry *entry)
{
glob_t gl;
char **ap;

View File

@ -50,7 +50,7 @@ sudo_dso_public int main(int argc, char *argv[]);
* reasonable expansion of the template and matches the fd. Returns true
* if all the X's were replaced with non-X's
*/
int
static int
check(int fd, char const *kind, char const *path, char const *prefix,
size_t plen, char const *suffix, size_t slen, int tlen)
{
@ -86,7 +86,7 @@ check(int fd, char const *kind, char const *path, char const *prefix,
return 1;
}
void
static void
try_mkdtemp(char *p, char const *prefix, int len)
{
size_t plen = strlen(prefix);
@ -105,7 +105,7 @@ try_mkdtemp(char *p, char const *prefix, int len)
sudo_fatalx("mkdtemp: exceeded MAX_TRIES");
}
void
static void
try_mkstemps(char *p, char const *prefix, int len, char const *suffix)
{
size_t plen = strlen(prefix);

View File

@ -0,0 +1,178 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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 <config.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SUDO_ERROR_WRAP 0
#include "sudo_compat.h"
#include "sudo_fatal.h"
#include "sudo_util.h"
sudo_dso_public int main(int argc, char *argv[]);
#ifdef __linux__
# include <sys/utsname.h>
# if defined(__ILP32__)
# define ARCH_LIB "libx32"
# elif defined(__LP64__)
# define ARCH_LIB "lib64"
# else
# define ARCH_LIB "lib32"
# endif
struct multiarch_test {
const char *inpath;
char *outpath;
};
static struct multiarch_test *
make_test_data(void)
{
struct multiarch_test *test_data;
struct utsname unamebuf;
int i;
if (uname(&unamebuf) == -1)
return NULL;
test_data = calloc(7, sizeof(*test_data));
if (test_data == NULL)
return NULL;
test_data[0].inpath = "/usr/" ARCH_LIB "/libfoo.so";
i = asprintf(&test_data[0].outpath, "/usr/lib/%s-linux-gnu/libfoo.so",
unamebuf.machine);
if (i == -1) {
test_data[0].outpath = NULL;
goto bad;
}
test_data[1].inpath = "/usr/lib/something.so";
i = asprintf(&test_data[1].outpath, "/usr/lib/%s-linux-gnu/something.so",
unamebuf.machine);
if (i == -1) {
test_data[1].outpath = NULL;
goto bad;
}
test_data[2].inpath = "/usr/libexec/libbar.so";
i = asprintf(&test_data[2].outpath, "/usr/libexec/%s-linux-gnu/libbar.so",
unamebuf.machine);
if (i == -1) {
test_data[2].outpath = NULL;
goto bad;
}
test_data[3].inpath = "/usr/local/lib/sudo/libsudo_util.so";
i = asprintf(&test_data[3].outpath, "/usr/local/lib/%s-linux-gnu/sudo/libsudo_util.so",
unamebuf.machine);
if (i == -1) {
test_data[3].outpath = NULL;
goto bad;
}
test_data[4].inpath = "/opt/sudo/lib/sudoers.so";
i = asprintf(&test_data[4].outpath, "/opt/sudo/lib/%s-linux-gnu/sudoers.so",
unamebuf.machine);
if (i == -1) {
test_data[4].outpath = NULL;
goto bad;
}
i = asprintf(&test_data[5].outpath, "/usr/lib/%s-linux-gnu/something.so",
unamebuf.machine);
if (i == -1) {
test_data[5].outpath = NULL;
goto bad;
}
test_data[5].inpath = test_data[5].outpath;
test_data[5].outpath = NULL;
return test_data;
bad:
for (i = 0; test_data[i].outpath != NULL; i++)
free(test_data[i].outpath);
free(test_data);
return NULL;
}
#endif /* __linux__ */
int
main(int argc, char *argv[])
{
int ch, errors = 0;
#ifdef __linux__
int ntests = 0;
struct multiarch_test *test_data;
#endif
initprogname(argc > 0 ? argv[0] : "multiarch_test");
while ((ch = getopt(argc, argv, "v")) != -1) {
switch (ch) {
case 'v':
/* ignore */
break;
default:
fprintf(stderr, "usage: %s [-v]\n", getprogname());
return EXIT_FAILURE;
}
}
argc -= optind;
argv += optind;
#ifdef __linux__
test_data = make_test_data();
if (test_data == NULL) {
sudo_warnx("%s", "failed to generate test data");
return EXIT_FAILURE;
}
for (ch = 0; test_data[ch].inpath != NULL; ch++) {
char *outpath = sudo_stat_multiarch(test_data[ch].inpath, NULL);
ntests++;
if (outpath == NULL) {
if (test_data[ch].outpath != NULL) {
sudo_warnx("%s: sudo_stat_multiarch failed",
test_data[ch].inpath);
errors++;
}
} else if (strcmp(outpath, test_data[ch].outpath) != 0) {
sudo_warnx("%s: expected %s got %s", test_data[ch].inpath,
test_data[ch].outpath, outpath);
errors++;
free(outpath);
}
}
if (ntests != 0) {
printf("%s: %d tests run, %d errors, %d%% success rate\n",
getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
}
#endif /* __linux__ */
return errors;
}

Some files were not shown because too many files have changed in this diff Show More