summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/CONTRIBUTORS245
-rw-r--r--doc/HISTORY76
-rw-r--r--doc/LICENSE347
-rw-r--r--doc/Makefile.in421
-rw-r--r--doc/TROUBLESHOOTING295
-rw-r--r--doc/UPGRADE534
-rw-r--r--doc/cvtsudoers.man.in513
-rw-r--r--doc/cvtsudoers.mdoc.in439
-rwxr-xr-xdoc/fixman.sh39
-rw-r--r--doc/fixmdoc.sed5
-rw-r--r--doc/schema.ActiveDirectory255
-rw-r--r--doc/schema.OpenLDAP78
-rw-r--r--doc/schema.iPlanet12
-rw-r--r--doc/schema.olcSudo79
-rw-r--r--doc/sudo.conf.man.in864
-rw-r--r--doc/sudo.conf.man.in.sed15
-rw-r--r--doc/sudo.conf.mdoc.in796
-rw-r--r--doc/sudo.man.in1495
-rw-r--r--doc/sudo.man.in.sed76
-rw-r--r--doc/sudo.mdoc.in1383
-rw-r--r--doc/sudo_logsrv.proto.man.in899
-rw-r--r--doc/sudo_logsrv.proto.mdoc.in817
-rw-r--r--doc/sudo_logsrvd.conf.man.in769
-rw-r--r--doc/sudo_logsrvd.conf.mdoc.in712
-rw-r--r--doc/sudo_logsrvd.man.in438
-rw-r--r--doc/sudo_logsrvd.mdoc.in396
-rw-r--r--doc/sudo_plugin.man.in5147
-rw-r--r--doc/sudo_plugin.mdoc.in4553
-rw-r--r--doc/sudo_plugin_python.man.in1890
-rw-r--r--doc/sudo_plugin_python.mdoc.in1541
-rw-r--r--doc/sudo_sendlog.man.in190
-rw-r--r--doc/sudo_sendlog.mdoc.in176
-rw-r--r--doc/sudoers.ldap.man.in1727
-rw-r--r--doc/sudoers.ldap.mdoc.in1588
-rw-r--r--doc/sudoers.man.in6548
-rw-r--r--doc/sudoers.man.in.sed150
-rw-r--r--doc/sudoers.mdoc.in6051
-rw-r--r--doc/sudoers_timestamp.man.in312
-rw-r--r--doc/sudoers_timestamp.mdoc.in290
-rw-r--r--doc/sudoreplay.man.in519
-rw-r--r--doc/sudoreplay.mdoc.in461
-rw-r--r--doc/visudo.man.in475
-rw-r--r--doc/visudo.mdoc.in457
43 files changed, 44073 insertions, 0 deletions
diff --git a/doc/CONTRIBUTORS b/doc/CONTRIBUTORS
new file mode 100644
index 0000000..44e0d35
--- /dev/null
+++ b/doc/CONTRIBUTORS
@@ -0,0 +1,245 @@
+The following list of people, sorted by last name, have contributed
+code or patches to this implementation of sudo since I began
+maintaining it in 1993. This list is known to be incomplete--if
+you believe you should be listed, please send a note to sudo@sudo.ws.
+
+ Ackeret, Matt
+ Adler, Mark
+ Allbery, Russ
+ Anderson, Jamie
+ Andrew, Nick
+ Andric, Dimitry
+ Barron, Danny
+ Bates, Tom
+ Behan, Zdeněk
+ Bellis, Ray
+ Benali, Elias
+ Beverly, Jamie
+ Boardman, Spider
+ Bos, Sander
+ Bostley, P.J.
+ Bowes, Keith
+ Boyce, Keith Garry
+ Brantley, Michael
+ Braun, Rob
+ Březina, Pavel
+ Brooks, Piete
+ Brown, Jerry
+ Burr, Michael E
+ Burton, Ross
+ Bussjaeger, Andreas
+ Calvin, Gary
+ Campbell, Aaron
+ Chazelas, Stephane
+ Cheloha, Scott
+ Čížek, Vítězslav
+ Coleman, Chris
+ Corzine, Deven T.
+ Cusack, Frank
+ Dai, Wei
+ Dill, David
+ Earickson, Jeff
+ Eckhardt, Drew
+ Edgington, Ben
+ Esipovich, Marc
+ Espie, Marc
+ Faigon, Ariel
+ Farrell, Brian
+ Fobes, Steve
+ Frysinger, Mike
+ G., Daniel Richard
+ Gailly, Jean-loup
+ Gelman, Stephen
+ Gerraty, Simon J.
+ Graber, Stephane
+ Guillory, B.
+ Hayman, Randy M.
+ Henke, Joachim
+ Hideaki, Yoshifuji
+ Hieb, Dave
+ Holloway, Nick
+ Hoover, Adam
+ Hunter, Michael T.
+ Hutchings, Ben
+ Irrgang, Eric
+ Jackson, Brian
+ Jackson, John R.
+ Jackson, Richard L., Jr.
+ Janssen, Mark
+ Jepeway, Chris
+ Jorge, Joel Peláe
+ Jover, Guillem
+ Juhani, Timo
+ Kikuchi, Ayamura
+ Kadow, Kevin
+ Kasal, Stepan
+ Kienenberger, Mike
+ King, Dale
+ King, Michael
+ Klyachkin, Andrey
+ Knoble, Jim
+ Knox, Tim
+ Komarnitsky, Alek O.
+ Kondrashov, Nikolai
+ Kopeček, Daniel
+ Kranenburg, Paul
+ Krause, David
+ Lakin, Eric
+ Larsen, Case
+ Levin, Dmitry V.
+ Libby, Kendall
+ Lobbes, Phillip E.
+ McIntyre, Jason
+ MacKenzie, David J.
+ McLaughlin, Tom
+ Makey, Jeff
+ Mallayya, Sangamesh
+ Manner, Róbert
+ Marchionna, Michael D.
+ Markham, Paul
+ Martinian, Emin
+ Meskes, Michael
+ Michael, David
+ Miller, Todd C.
+ Minier, Loïc
+ Moffat, Darren
+ Moldung, Jan Thomas
+ Morris, Charles
+ Mueller, Andreas
+ Müller, Dworkin
+ Nieusma, Jeff
+ Nikitser, Peter A.
+ Nussel, Ludwig
+ Orbán, László
+ Ouellet, Jean-Philippe
+ Paquet, Eric
+ Paradis, Chantal
+ Pasteleurs, Frederic
+ Percival, Ted
+ Perera, Andres
+ Peron, Christian S.J.
+ Peschel, Aaron
+ Peslyak, Alexander
+ Peterson, Toby
+ Pettenò, Diego Elio
+ Pickett, Joel
+ Plotnick, Alex
+ de Raadt, Theo
+ Rasch, Gudleik
+ Reid, Steve
+ Richards, Matt
+ Rossum, Guido van
+ Rouillard, John P.
+ Rowe, William A., Jr.
+ Roy, Alain
+ Ruusamäe, Elan
+ Ryabinkin, Eygene
+ Sato, Yuichi
+ Sánchez, Wilfredo
+ Sanders, Miguel
+ Sasaki, Kan
+ Saucier, Jean-Francois
+ Schoenfeld, Patrick
+ Schuring, Arno
+ Schwarze, Ingo
+ Scott, Dougal
+ Sieger, Nick
+ Simon, Thor Lancelot
+ Slemko, Marc
+ Smith, Andy
+ Sobrado, Igor
+ Soulen, Steven
+ Spangler, Aaron
+ Spradling, Cloyce D.
+ Spradling, Michael
+ Stier, Matthew
+ Stoeckmann, Tobias
+ Street, Russell
+ Stritzky, Tilo
+ Stroucken, Michael
+ Tarrall, Robert
+ Thomas, Matthew
+ Todd, Giles
+ Toft, Martin
+ Torek, Chris
+ Tucker, Darren
+ Uhl, Robert
+ Uzel, Petr
+ Valery, Reznic
+ Van Dinter, Theo
+ Venckus, Martynas
+ de Vries, Maarten
+ Wagner, Klaus
+ Walsh, Dan
+ Warburton, John
+ Webb, Kirk
+ Wetzel, Timm
+ Wieringen, Marco van
+ Wilk, Jakub
+ Winiger, Gary
+ Wood, David
+ Zacarias, Gustavo
+ Zolnowsky, John
+
+The following people have worked to translate sudo into
+other languages as part of the Translation Project, see
+https://translationproject.org for more details.
+
+ Albuquerque, Pedro
+ Blättermann, Mario
+ Bogusz, Jakub
+ Buo-ren, Lin
+ Casagrande, Milo
+ Castro, Felipe
+ Cho, Seong-ho
+ Chornoivan, Yuri
+ Diéguez, Francisco
+ Fontenelle, Rafael
+ García-Fontes, Walter
+ Gezer, Volkan
+ Hamasaki, Takeshi
+ Hamming, Peter
+ Hansen, Joe
+ Hantrais, Frédéric
+ Hein, Jochen
+ Hufthammer, Karl Ove
+ Jerovšek, Damir
+ Karvonen, Jorma
+ Kazik, Dušan
+ Kelemen, Gábor
+ Keçeci, Mehmet
+ Košir, Klemen
+ Kozlov, Yuri
+ Kramer, Jakob
+ Krznar, Tomislav
+ Marchal, Frédéric
+ Margevičius, Algimantas
+ Maryanov, Pavel
+ Florentina Mușat
+ Nurmi, Lauri
+ Nikolić, Miroslav
+ Nylander, Daniel
+ Pan, Yi-Jyun
+ Písař, Petr
+ Puente, Enol
+ Putanec, Božidar
+ Quân, Trần Ngọc
+ Rasmussen, Sebastian
+ Regueiro, Leandro
+ Sarıer, Özgür
+ Sendón, Abel
+ Șerbănescu, Daniel
+ Sikrom, Åka
+ Spingos, Dimitris
+ Taniguchi, Yasuaki
+ Tomat, Fábio
+ Úr, Balázs
+ Uranga, Mikel Olasagasti
+ Vorotnikov, Artem
+ Wang, Wylmer
+ Yang, Boyuan
+
+The following people designed the artwork used on the sudo website:
+
+ Shield logo: Badger, Trent
+ Sandwich logo: Stillman, Mark
diff --git a/doc/HISTORY b/doc/HISTORY
new file mode 100644
index 0000000..0ad9512
--- /dev/null
+++ b/doc/HISTORY
@@ -0,0 +1,76 @@
+A Brief History of Sudo:
+
+The Early Years
+
+Sudo was first conceived and implemented by Bob Coggeshall and Cliff Spencer
+around 1980 at the Department of Computer Science at SUNY/Buffalo. It ran on
+a VAX-11/750 running 4.1BSD. An updated version, credited to Phil Betchel,
+Cliff Spencer, Gretchen Phillips, John LoVerso and Don Gworek, was posted to
+the net.sources Usenet newsgroup in December of 1985.
+
+Sudo at CU-Boulder
+
+In the Summer of 1986, Garth Snyder released an enhanced version of sudo.
+For the next 5 years, sudo was fed and watered by a handful of folks at
+CU-Boulder, including Bob Coggeshall, Bob Manchek, and Trent Hein.
+
+Root Group Sudo
+
+In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo with an
+enhanced sudoers format under contract to a consulting firm called "The Root
+Group". This version was later released under the GNU public license.
+
+CU Sudo
+
+In 1994, after maintaining sudo informally within CU-Boulder for some time,
+Todd C. Miller made a public release of "CU sudo" (version 1.3) with bug
+fixes and support for more operating systems. The "CU" was added to
+differentiate it from the "official" version from "The Root Group".
+
+In 1995, a new parser for the sudoers file was contributed by Chris Jepeway.
+The new parser was a proper grammar (unlike the old one) and could work with
+both sudo and visudo (previously they had slightly different parsers).
+
+In 1996, Todd, who had been maintaining sudo for several years in his spare
+time, moved distribution of sudo from a CU-Boulder ftp site to his domain,
+courtesan.com.
+
+Just Plain Sudo
+
+In 1999, the "CU" prefix was dropped from the name since there had been no
+formal release of sudo from "The Root Group" since 1991 (the original
+authors now work elsewhere). As of version 1.6, Sudo no longer contains any
+of the original "Root Group" code and is available under an ISC-style
+license.
+
+In 2001, the sudo web site, ftp site and mailing lists were moved from
+courtesan.com to the sudo.ws domain (sudo.org was already taken).
+
+LDAP Integration
+
+In 2003, Nationwide Mutual Insurance Company contributed code written by
+Aaron Spangler to store the sudoers data in LDAP. These changes were
+incorporated into Sudo 1.6.8.
+
+New Parser
+
+In 2005, Todd rewrote the sudoers parser to better support the features that
+had been added in the past ten years. This new parser removes some
+limitations of the previous one, removes ordering constraints and adds
+support for including multiple sudoers files.
+
+Quest Sponsorship
+
+In 2010, Quest Software began sponsoring Sudo development by hiring
+Todd to work on Sudo as part of his full-time job. This enabled
+the addition of I/O logging, the plugin interface, additional
+regression tests, support for binary packages and more regular
+releases.
+
+Present Day
+
+Sudo, in its current form, is maintained by:
+
+ Todd C. Miller <Todd.Miller@sudo.ws>
+
+Todd continues to enhance sudo and fix bugs.
diff --git a/doc/LICENSE b/doc/LICENSE
new file mode 100644
index 0000000..60f193f
--- /dev/null
+++ b/doc/LICENSE
@@ -0,0 +1,347 @@
+Sudo is distributed under the following license:
+
+ Copyright (c) 1994-1996, 1998-2021
+ 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.
+
+ Sponsored in part by the Defense Advanced Research Projects
+ Agency (DARPA) and Air Force Research Laboratory, Air Force
+ Materiel Command, USAF, under agreement number F39502-99-1-0512.
+
+The Python plugin bindings bear the following license:
+
+ Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+
+ 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.
+
+The files hostcheck.c and hostcheck.h bear the following license:
+
+ Copyright (c) 2020 Laszlo Orban <laszlo.orban@oneidentity.com>
+
+ 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.
+
+The file redblack.c bears the following license:
+
+ Copyright (c) 2001 Emin Martinian
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that neither the name of Emin
+ Martinian nor the names of any contributors are be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The file sssd.c bears the following license:
+
+ Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
+
+ This code is derived from software contributed by Aaron Spangler.
+
+ 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.
+
+The files bsm_audit.c and bsm_audit.h bear the following license:
+
+ Copyright (c) 2009 Christian S.J. Peron
+
+ 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.
+
+The files solaris_audit.c and solaris_audit.h bear the following license:
+
+ Copyright (c) 2014, Oracle and/or its affiliates.
+
+ 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.
+
+The file reallocarray.c bears the following license:
+
+ Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The files getcwd.c, glob.c, glob.h, snprintf.c and sudo_queue.h bear the
+following license:
+
+ Copyright (c) 1989, 1990, 1991, 1993
+ The Regents of the University of California. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+The file fnmatch.c bears the following license:
+
+ Copyright (c) 2011, VMware, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the VMware, Inc. nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The file getopt_long.c bears the following license:
+
+ Copyright (c) 2000 The NetBSD Foundation, Inc.
+ All rights reserved.
+
+ This code is derived from software contributed to The NetBSD Foundation
+ by Dieter Baron and Thomas Klausner.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+The file inet_pton.c bears the following license:
+
+ Copyright (c) 1996 by Internet Software Consortium.
+
+ 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ CONSORTIUM 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.
+
+The file arc4random.c bears the following license:
+
+ Copyright (c) 1996, David Mazieres <dm@uun.org>
+ Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+
+ 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.
+
+The file arc4random_uniform.c bears the following license:
+
+ Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+
+ 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.
+
+The file getentropy.c bears the following license:
+
+ Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+
+ 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.
+
+The embedded copy of zlib bears the following license:
+
+ Copyright (C) 1995-2017 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+The embedded copy of protobuf-c bears the following license:
+
+ Copyright (c) 2008-2018, Dave Benson and the protobuf-c authors.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..e5e89de
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,421 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2015, 2017-2020 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.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+docdir = @docdir@
+scriptdir = $(top_srcdir)/scripts
+
+# Tools to use
+SED = @SED@
+IGOR = igor
+MANDOC = @MANDOCPROG@
+MANCOMPRESS = @MANCOMPRESS@
+MANCOMPRESSEXT = @MANCOMPRESSEXT@
+TR = @TRPROG@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(top_srcdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+
+# Directory in which to install the man page
+mantype = @MANTYPE@
+mansectsu = @mansectsu@
+mansectform = @mansectform@
+mandirexe = $(mandir)/@MANDIRTYPE@1
+mandirsu = $(mandir)/@MANDIRTYPE@$(mansectsu)
+mandirform = $(mandir)/@MANDIRTYPE@$(mansectform)
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+DOCS = ./cvtsudoers.$(mantype) ./sudo.$(mantype) ./sudo.conf.$(mantype) \
+ ./sudo_logsrvd.$(mantype) ./sudo_logsrv.proto.$(mantype) \
+ ./sudo_logsrvd.conf.$(mantype) ./sudo_plugin.$(mantype) \
+ ./sudo_plugin_python.$(mantype) ./sudo_sendlog.$(mantype) \
+ ./sudoers.$(mantype) ./sudoers.ldap.$(mantype) \
+ ./sudoers_timestamp.$(mantype) \
+ ./sudoreplay.$(mantype) ./visudo.$(mantype)
+
+DEVDOCS = $(srcdir)/cvtsudoers.man.in $(srcdir)/sudo.conf.man.in \
+ $(srcdir)/sudo.man.in $(srcdir)/sudo_logsrvd.man.in \
+ $(srcdir)/sudo_logsrv.proto.man.in \
+ $(srcdir)/sudo_logsrvd.conf.man.in \
+ $(srcdir)/sudo_plugin.man.in $(srcdir)/sudo_plugin_python.man.in \
+ $(srcdir)/sudo_sendlog.man.in $(srcdir)/sudoers.ldap.man.in \
+ $(srcdir)/sudoers.man.in $(srcdir)/sudoers_timestamp.man.in \
+ $(srcdir)/sudoreplay.man.in $(srcdir)/visudo.man.in
+
+OTHER_DOCS = $(top_srcdir)/ChangeLog $(top_srcdir)/README \
+ $(top_srcdir)/NEWS $(srcdir)/HISTORY $(srcdir)/CONTRIBUTORS \
+ $(srcdir)/LICENSE $(srcdir)/TROUBLESHOOTING $(srcdir)/UPGRADE
+
+OTHER_DOCS_LDAP = $(top_srcdir)/README.LDAP $(srcdir)/schema.*
+
+VERSION = @PACKAGE_VERSION@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+all: $(DEVDOCS) $(DOCS)
+
+igor: all
+ @if [ "$(mantype)" != "mdoc" ]; then \
+ echo "make igor only supported for mdoc manuals" 1>&2; \
+ exit 1; \
+ else \
+ rval=0; \
+ for m in $(DOCS); do \
+ echo $(IGOR) -D $$m; \
+ $(IGOR) -D $$m || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval; \
+ fi
+
+lint: all
+ @if [ "$(mantype)" != "mdoc" ]; then \
+ echo "make lint only supported for mdoc manuals" 1>&2; \
+ exit 1; \
+ else \
+ rval=0; \
+ for m in $(DOCS); do \
+ echo $(MANDOC) -Tlint -Wstyle $$m; \
+ $(MANDOC) -Tlint -Wstyle $$m || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval; \
+ fi
+
+depend:
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file doc/Makefile
+
+.SUFFIXES: .man
+
+$(srcdir)/sudo.man.in: $(srcdir)/sudo.mdoc.in $(srcdir)/sudo.man.in.sed
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudo.man.in.sed > $@; \
+ fi
+
+fixman.sed: $(srcdir)/fixman.sh
+ $(SHELL) $(srcdir)/fixman.sh $@
+
+./sudo.man: $(top_builddir)/config.status $(srcdir)/sudo.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo.man.in | $(SED) -f fixman.sed > $@
+
+./sudo.mdoc: $(top_builddir)/config.status $(srcdir)/sudo.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/visudo.man.in: $(srcdir)/visudo.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/visudo.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "VISUDO" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./visudo.man: $(top_builddir)/config.status $(srcdir)/visudo.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/visudo.man.in | $(SED) -f fixman.sed > $@
+
+./visudo.mdoc: $(top_builddir)/config.status $(srcdir)/visudo.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo.conf.man.in: $(srcdir)/sudo.conf.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo.conf.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO.CONF" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudo.conf.man.in.sed > $@; \
+ fi
+
+./sudo.conf.man: $(top_builddir)/config.status $(srcdir)/sudo.conf.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo.conf.man.in | $(SED) -f fixman.sed > $@
+
+./sudo.conf.mdoc: $(top_builddir)/config.status $(srcdir)/sudo.conf.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudoers.man.in: $(srcdir)/sudoers.mdoc.in $(srcdir)/sudoers.man.in.sed
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudoers.man.in.sed> $@; \
+ fi
+
+./sudoers.man: $(top_builddir)/config.status $(srcdir)/sudoers.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers.mdoc.in $(srcdir)/fixmdoc.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.mdoc.in | $(SED) -f $(srcdir)/fixmdoc.sed > $@
+
+$(srcdir)/sudoers.ldap.man.in: $(srcdir)/sudoers.ldap.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers.ldap.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS.LDAP" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoers.ldap.man: $(top_builddir)/config.status $(srcdir)/sudoers.ldap.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.ldap.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers.ldap.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers.ldap.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudoers_timestamp.man.in: $(srcdir)/sudoers_timestamp.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers_timestamp.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS_TIMESTAMP" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoers_timestamp.man: $(top_builddir)/config.status $(srcdir)/sudoers_timestamp.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers_timestamp.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers_timestamp.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers_timestamp.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/cvtsudoers.man.in: $(srcdir)/cvtsudoers.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/cvtsudoers.mdoc.in | $(MANDOC) -Tman | $(SED) -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./cvtsudoers.man: $(top_builddir)/config.status $(srcdir)/cvtsudoers.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/cvtsudoers.man.in | $(SED) -f fixman.sed > $@
+
+./cvtsudoers.mdoc: $(top_builddir)/config.status $(srcdir)/cvtsudoers.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudoreplay.man.in: $(srcdir)/sudoreplay.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoreplay.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOREPLAY" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoreplay.man: $(top_builddir)/config.status $(srcdir)/sudoreplay.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoreplay.man.in | $(SED) -f fixman.sed > $@
+
+./sudoreplay.mdoc: $(top_builddir)/config.status $(srcdir)/sudoreplay.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_logsrvd.man.in: $(srcdir)/sudo_logsrvd.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrvd.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRVD" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_logsrvd.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrvd.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrvd.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_logsrv.proto.man.in: $(srcdir)/sudo_logsrv.proto.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrv.proto.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRV.PROTO" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(5)/($$mansectform)/g" > $@; \
+ fi
+
+./sudo_logsrv.proto.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrv.proto.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrv.proto.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrv.proto.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrv.proto.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_logsrvd.conf.man.in: $(srcdir)/sudo_logsrvd.conf.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrvd.conf.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRVD.CONF" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(5)/($$mansectform)/g" > $@; \
+ fi
+
+./sudo_logsrvd.conf.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.conf.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrvd.conf.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrvd.conf.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.conf.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_plugin.man.in: $(srcdir)/sudo_plugin.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_plugin.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_PLUGIN" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_plugin.man: $(top_builddir)/config.status $(srcdir)/sudo_plugin.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_plugin.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_plugin.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_plugin.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_plugin_python.man.in: $(srcdir)/sudo_plugin_python.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_plugin_python.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_PLUGIN" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_plugin_python.man: $(top_builddir)/config.status $(srcdir)/sudo_plugin_python.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_plugin_python.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_plugin_python.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_plugin_python.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+$(srcdir)/sudo_sendlog.man.in: $(srcdir)/sudo_sendlog.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_sendlog.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_SENDLOG" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_sendlog.man: $(top_builddir)/config.status $(srcdir)/sudo_sendlog.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_sendlog.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_sendlog.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_sendlog.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=doc/$@
+
+pre-install:
+
+install: install-doc
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(docdir) \
+ $(DESTDIR)$(mandirexe) $(DESTDIR)$(mandirform) $(DESTDIR)$(mandirsu)
+
+install-binaries:
+
+install-includes:
+
+install-doc: install-dirs
+ for f in $(OTHER_DOCS); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $$f $(DESTDIR)$(docdir); done
+ @LDAP@for f in $(OTHER_DOCS_LDAP); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $$f $(DESTDIR)$(docdir); done
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./cvtsudoers.$(mantype) $(DESTDIR)$(mandirexe)/cvtsudoers.1
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo.$(mantype) $(DESTDIR)$(mandirsu)/sudo.$(mansectsu)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrvd.$(mantype) $(DESTDIR)$(mandirsu)/sudo_logsrvd.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_plugin.$(mantype) $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu)
+ @PYTHON_PLUGIN@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_plugin_python.$(mantype) $(DESTDIR)$(mandirsu)/sudo_plugin_python.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_sendlog.$(mantype) $(DESTDIR)$(mandirsu)/sudo_sendlog.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoreplay.$(mantype) $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo.conf.$(mantype) $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrv.proto.$(mantype) $(DESTDIR)$(mandirform)/sudo_logsrv.proto.$(mansectform)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrvd.conf.$(mantype) $(DESTDIR)$(mandirform)/sudo_logsrvd.conf.$(mansectform)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers_timestamp.$(mantype) $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform)
+ @LDAP@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform)
+ @if test -n "$(MANCOMPRESS)"; then \
+ for f in $(mandirexe)/cvtsudoers.1 $(mandirsu)/sudo.$(mansectsu) $(mandirsu)/sudo_logsrvd.$(mansectsu) $(mandirsu)/sudo_plugin.$(mansectsu) $(mandirsu)/sudo_plugin_python.$(mansectsu) $(mandirsu)/sudo_sendlog.$(mansectsu) $(mandirsu)/sudoreplay.$(mansectsu) $(mandirsu)/visudo.$(mansectsu) $(mandirform)/sudo.conf.$(mansectform) $(mandirform)/sudo_logsrv.proto.$(mansectform) $(mandirform)/sudo_logsrvd.conf.$(mansectform) $(mandirform)/sudoers.$(mansectform) $(mandirform)/sudoers_timestamp.$(mansectform) $(mandirform)/sudoers.ldap.$(mansectform); do \
+ if test -f $(DESTDIR)$$f; then \
+ echo $(MANCOMPRESS) -f $(DESTDIR)$$f; \
+ $(MANCOMPRESS) -f $(DESTDIR)$$f; \
+ fi; \
+ done; \
+ rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ echo ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ else \
+ rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ echo ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ fi
+
+install-plugin:
+
+uninstall:
+ -rm -rf $(DESTDIR)$(docdir)
+ -rm -f $(DESTDIR)$(mandirexe)/cvtsudoers.1 \
+ $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_logsrvd.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_plugin_python.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_sendlog.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \
+ $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_logsrv.proto.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_logsrvd.conf.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform)
+ $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform)
+
+splint:
+
+cppcheck:
+
+pvs-log-files:
+
+pvs-studio:
+
+check:
+
+clean:
+ -rm -f fixman.sed
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile config.log *.man *.mdoc
+
+clobber: distclean
+
+realclean: distclean
+
+cleandir: distclean
diff --git a/doc/TROUBLESHOOTING b/doc/TROUBLESHOOTING
new file mode 100644
index 0000000..bc7f1a6
--- /dev/null
+++ b/doc/TROUBLESHOOTING
@@ -0,0 +1,295 @@
+Troubleshooting tips and FAQ for Sudo
+=====================================
+
+Q) When I run configure, it says "C compiler cannot create executables".
+A) This usually means you either don't have a working compiler. This
+ could be due to the lack of a license or that some component of the
+ compiler suite could not be found. Check config.log for clues as
+ to why this is happening. On many systems, compiler components live
+ in /usr/ccs/bin which may not be in your PATH environment variable.
+
+Q) When I run configure, it says "sudo requires the 'ar' utility to build".
+A) As part of the build process, sudo creates a temporary library containing
+ objects that are shared amongst the different sudo executables.
+ On Unix systems, the "ar" utility is used to do this. This error
+ indicates that "ar" is missing on your system. On Solaris systems,
+ you may need to install the SUNWbtool package. On other systems
+ "ar" may be included in the GNU binutils package.
+
+Q) Sudo compiles and installs OK but when I try to run it I get:
+ /usr/local/bin/sudo must be owned by uid 0 and have the setuid bit set
+A) Sudo must be setuid root to do its work. Either /usr/local/bin/sudo
+ is not owned by uid 0 or the setuid bit is not set. This should have
+ been done for you by "make install" but you can fix it manually by
+ running the following as root:
+ # chown root /usr/local/bin/sudo; chmod 4755 /usr/local/bin/sudo
+
+Q) Sudo compiles and installs OK but when I try to run it I get:
+ effective uid is not 0, is /usr/local/bin/sudo on a file system with the
+ 'nosuid' option set or an NFS file system without root privileges?
+A) The owner and permissions on the sudo binary appear to be OK but when
+ sudo ran, the setuid bit did not have an effect. There are two common
+ causes for this. The first is that the file system the sudo binary
+ is located on is mounted with the 'nosuid' mount option, which disables
+ setuid binaries. The output of the "mount" command should tell you if
+ the file system is mounted with the 'nosuid' option. The other possible
+ cause is that sudo is installed on an NFS-mounted file system that is
+ exported without root privileges. By default, NFS file systems are
+ exported with uid 0 mapped to a non-privileged uid (usually -2). You
+ should be able to determine whether sudo is located on an NFS-mounted
+ filesystem by running "df `which sudo'".
+
+Q) Sudo never gives me a chance to enter a password using PAM, it just
+ says 'Sorry, try again.' three times and exits.
+A) You didn't setup PAM to work with sudo. On RedHat Linux or Fedora
+ Core this generally means installing the sample pam.conf file as
+ /etc/pam.d/sudo. See the example pam.conf file for hints on what
+ to use for other Linux systems.
+
+Q) Sudo says 'Account expired or PAM config lacks an "account"
+ section for sudo, contact your system administrator' and exits
+ but I know my account has not expired.
+A) Your PAM config lacks an "account" specification. On Linux this
+ usually means you are missing a line like:
+ account required pam_unix.so
+ in /etc/pam.d/sudo.
+
+Q) Sudo is setup to log via syslog(3) but I'm not getting any log
+ messages.
+A) Make sure you have an entry in your syslog.conf file to save
+ the sudo messages (see the example syslog.conf file). The default
+ log facility is authpriv (changeable via configure or in sudoers).
+ Don't forget to send a SIGHUP to your syslogd so that it re-reads
+ its conf file. Also, remember that syslogd does *not* create
+ log files, you need to create the file before syslogd will log
+ to it (ie: touch /var/log/sudo).
+ Note: the facility (e.g. "auth.debug") must be separated from the
+ destination (e.g. "/var/log/auth" or "@loghost") by
+ tabs, *not* spaces. This is a common error.
+
+Q) When sudo asks me for my password it never accepts what I enter even
+ though I know I entered my password correctly.
+A) If you are not using pam and your system uses shadow passwords,
+ it is possible that sudo didn't properly detect that shadow
+ passwords are in use. Take a look at the generated config.h
+ file and verify that the C function used for shadow password
+ look ups was detected. For instance, for SVR4-style shadow
+ passwords, HAVE_GETSPNAM should be defined (you can search for
+ the string "shadow passwords" in config.h with your editor).
+ Note that there is no define for 4.4BSD-based shadow passwords
+ since that just uses the standard getpw* routines.
+
+Q) Can sudo use the ssh agent for authentication instead of asking
+ for the user's Unix password?
+A) Not directly, but you can use a PAM module like pam_ssh_agent_auth
+ or pam_ssh for this purpose.
+
+Q) I don't want the sudoers file in /etc, how can I specify where it
+ should go?
+A) Use the --sysconfdir option to configure. Ie:
+ configure --sysconfdir=/dir/you/want/sudoers/in
+
+Q) Can I put the sudoers file in NIS/NIS+ or do I have to have a
+ copy on each machine?
+A) There is no support for making an NIS/NIS+ map/table out of
+ the sudoers file at this time. You can distribute the sudoers
+ file via rsync or rdist. It is also possible to NFS-mount the
+ sudoers file. If you use LDAP at your site you may be interested
+ in sudo's LDAP sudoers support, see the README.LDAP file and the
+ sudoers.ldap manual.
+
+Q) I don't run sendmail on my machine. Does this mean that I cannot
+ use sudo?
+A) No, you just need to disable mailing with a line like:
+ Defaults !mailerpath
+ in your sudoers file or run configure with the --without-sendmail
+ option.
+
+Q) When I run visudo it uses vi as the editor and I hate vi. How
+ can I make it use another editor?
+A) You can specify the editor to use in visudo in the sudoers file.
+ See the "editor" and "env_editor" entries in the sudoers manual.
+ The defaults can also be set at configure time using the
+ --with-editor and --with-env-editor configure options.
+
+Q) Sudo appears to be removing some variables from the environment, why?
+A) By default, sudo runs commands with a new, minimal environment.
+ The "env_keep" setting in sudoers can be used to control which
+ environment variables are preserved from the invoking user's
+ environment via the "env_keep" setting in sudoers.
+
+ While it is possible to disable the "env_reset" setting, which
+ will preserve all environment variables that don't match a black
+ list, doing so is strongly discouraged. See the "Command
+ environment" section of the sudoers manual for more information.
+
+Q) Why does sudo reset the HOME environment variable?
+A) Many programs use the HOME environment variable to locate
+ configuration and data files. Often, these configuration files
+ are treated as trusted input that affects how the program operates.
+ By controlling the configuration files, a user may be able to
+ cause the program to execute other commands without sudo's
+ restrictions or logging.
+
+ Some programs perform extra checks when the real and effective
+ user-IDs differ, but because sudo runs commands with all user-IDs
+ set to the target user, these checks are insufficient.
+
+ While it is possible to preserve the value of the HOME environment
+ variable by adding it to the "env_keep" list in the sudoers file,
+ doing so is strongly discouraged. Users wishing to edit files
+ with sudo should run sudoedit (or sudo -e) to get their accustomed
+ editor configuration instead of invoking the editor directly.
+
+Q) How can I keep sudo from asking for a password?
+A) To specify this on a per-user (and per-command) basis, use the
+ 'NOPASSWD' tag right before the command list in sudoers. See
+ the sudoers man page and examples/sudoers for details. To disable
+ passwords completely, add !authenticate" to the Defaults line
+ in /etc/sudoers. You can also turn off authentication on a
+ per-user or per-host basis using a user or host-specific Defaults
+ entry in sudoers. To hard-code the global default, you can
+ configure with the --without-passwd option.
+
+Q) When I run configure, it dies with the following error:
+ "no acceptable cc found in $PATH".
+A) /usr/ucb/cc was the only C compiler that configure could find.
+ You need to tell configure the path to the "real" C compiler
+ via the --with-CC option. On Solaris, the path is probably
+ something like "/opt/SUNWspro/SC4.0/bin/cc". If you have gcc
+ that will also work.
+
+Q) When I run configure, it dies with the following error:
+ Fatal Error: config.cache exists from another platform!
+ Please remove it and re-run configure.
+A) configure caches the results of its tests in a file called
+ config.cache to make re-running configure speedy. However,
+ if you are building sudo for a different platform the results
+ in config.cache will be wrong so you need to remove config.cache.
+ You can do this by "rm config.cache" or "make realclean".
+ Note that "make realclean" will also remove any object files
+ and configure temp files that are laying around as well.
+
+Q) I built sudo on a Solaris 11 (or higher) machine but the resulting
+ binary doesn't work older Solaris versions. Why?
+A) Starting with Solaris 11, asprintf(3) is included in the standard
+ C library. To build a version of sudo on a Solaris 11 machine that
+ will run on an older Solaris release, edit config.h and comment out
+ the lines:
+ #define HAVE_ASPRINTF 1
+ #define HAVE_VASPRINTF 1
+ and run make.
+
+Q) When I run "visudo" it says "sudoers file busy, try again later."
+ and doesn't do anything.
+A) Someone else is currently editing the sudoers file with visudo.
+
+Q) When I try to use "cd" with sudo it says "cd: command not found".
+A) "cd" is a shell built-in command, you can't run it as a command
+ since a child process (sudo) cannot affect the current working
+ directory of the parent (your shell).
+
+Q) When I try to use "cd" with sudo the command completes without
+ errors but nothing happens.
+A) Even though "cd" is a shell built-in command, some operating systems
+ include a /usr/bin/cd command for some reason. A standalone
+ "cd" command is totally useless since a child process (cd) cannot
+ affect the current working directory of the parent (your shell).
+ Thus, "sudo cd /foo" will start a child process, change the
+ directory and immediately exit without doing anything useful.
+
+Q) When I run sudo it says I am not allowed to run the command as root
+ but I don't want to run it as root, I want to run it as another user.
+ My sudoers file entry looks like:
+ bob ALL=(oracle) ALL
+A) The default user sudo tries to run things as is always root, even if
+ the invoking user can only run commands as a single, specific user.
+ This may change in the future but at the present time you have to
+ work around this using the 'runas_default' option in sudoers.
+ For example:
+ Defaults:bob runas_default=oracle
+ would achieve the desired result for the preceding sudoers fragment.
+
+Q) When I try to run sudo via ssh, I get the error:
+ sudo: a terminal is required to read the password; either use the -S
+ option to read from standard input or configure an askpass helper
+A) If sudo needs to authenticate a user, it requires access to the user's
+ terminal to disable echo so the password is not displayed to the screen.
+ The above message indicates that no terminal was present.
+
+ When running a command via ssh, a terminal is not allocated by default
+ which can cause this message. The "-t" option to ssh will force it to
+ allocate a tty. Alternately, you may be able to use the ssh-askpass
+ utility to prompt for the password if X11 forwarding is enabled and an
+ askpass helper is configured in the sudo.conf file. If you do not mind
+ your password being echoed to the screen, you may use sudo's -S option
+ to read the password from the standard input. Alternately, you may set
+ the "visiblepw" sudoers option which will allow the password to be entered
+ even when echo cannot be disabled, though this is not recommended.
+
+Q) When I try to use SSL-enabled LDAP with sudo I get an error:
+ unable to initialize SSL cert and key db: security library: bad database.
+ you must set TLS_CERT in /etc/ldap.conf to use SSL
+A) On systems that use a Mozilla-derived LDAP SDK there must be a
+ certificate database in place to use SSL-encrypted LDAP connections.
+ This file is usually /var/ldap/cert8.db or /etc/ldap/cert8.db.
+ The actual number after "cert" will vary, depending on the version
+ of the LDAP SDK that is being used. If you do not have a certificate
+ database you can either copy one from a mozilla-derived browser, such
+ as firefox, or create one using the "certutil" command. You can run
+ "certutil" as follows and press the <return> (or <enter>) key at the
+ password prompt:
+ # certutil -N -d /var/ldap
+ Enter a password which will be used to encrypt your keys.
+ The password should be at least 8 characters long,
+ and should contain at least one non-alphabetic character.
+
+ Enter new password: <return>
+ Re-enter password: <return>
+
+Q) On HP-UX, the umask setting in sudoers has no effect.
+A) If your /etc/pam.conf file has the libpam_hpsec.so.1 session module
+ enabled, you may need to a add line like the following to pam.conf:
+ sudo session required libpam_hpsec.so.1 bypass_umask
+
+Q) When I run "sudo -i shell_alias" I get "command not found" even
+ though the alias is defined in my shell startup files.
+A) Commands run via "sudo -i" are executed by the shell in
+ non-interactive mode. The bash shell will only parse aliases in
+ interactive mode unless the "expand_aliases" shell option is
+ set. If you add "shopt -s expand_aliases" to your .bash_profile
+ (or .profile if using that instead) the aliases should now be
+ available to "sudo -i".
+
+Q) When I run sudo on AIX I get the following error:
+ setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID): Operation not permitted.
+A) AIX's Enhanced RBAC is preventing sudo from running. To fix
+ this, add the following entry to /etc/security/privcmds (adjust
+ the path to sudo as needed) and run the setkst command as root:
+
+ /usr/local/bin/sudo:
+ accessauths = ALLOW_ALL
+ innateprivs = PV_DAC_GID,PV_DAC_R,PV_DAC_UID,PV_DAC_X,PV_FS_CHOWN,PV_PROC_PRIO,PV_NET_PORT,PV_NET_CNTL,PV_SU_UID
+ secflags = FSF_EPS
+
+Q) Sudo configures and builds without error but when I run it I get
+ a Segmentation fault.
+A) If you are on a Linux system, the first thing to try is to run
+ configure with the --disable-pie option, then "make clean" and
+ "make". If that fixes the problem then your operating system
+ does not properly support position independent executables.
+ Please send a message to sudo@sudo.ws with system details such
+ as the Linux distro, kernel version and CPU architecture.
+
+Q) When I run configure I get the following error:
+ dlopen present but libtool doesn't appear to support your platform.
+A) Libtool doesn't know how to support dynamic linking on the operating
+ system you are building for. If you are cross-compiling, you need to
+ specify the operating system, not just the CPU type. For example:
+ --host powerpc-unknown-linux
+ instead of just:
+ --host powerpc
+
+Q) How do you pronounce `sudo'?
+A) The official pronunciation is soo-doo (for su "do"). However, an
+ alternate pronunciation, a homophone of "pseudo", is also common.
diff --git a/doc/UPGRADE b/doc/UPGRADE
new file mode 100644
index 0000000..7d03777
--- /dev/null
+++ b/doc/UPGRADE
@@ -0,0 +1,534 @@
+Notes on upgrading from an older release
+========================================
+
+o Upgrading from a version prior to 1.9.3:
+
+ Due to the addition of the CHROOT and CWD options, it is no
+ longer possible to declare an alias with one of those names.
+ If a sudoers file has an alias with one of those names, sudo
+ and visudo will report a syntax error with a message like
+ "syntax error: unexpected CHROOT, expecting ALIAS".
+
+ Starting with version 1.9.3, sudoers rules must end in either
+ a newline or the end-of-file. This makes it possible to provide
+ better error messages. Previously, it was possible to include
+ multiple rules on a single line, separated by white space.
+
+ Starting with version 1.9.3, sudo will attempt to recover from
+ a syntax error in the sudoers file by discarding the portion
+ of the line that contains the error until the end of the line.
+ To restore the historic behavior of refusing to run when a
+ syntax error is encountered, add "error_recovery=false" as a
+ plugin option in sudo.conf for the "sudoers_audit" plugin, (or
+ "sudoers_policy" if there is no "sudoers_audit" plugin configured).
+
+o Upgrading from a version prior to 1.9.1:
+
+ Starting with version 1.9.1, sudoers plugin arguments in sudo.conf
+ should be specified for the "sudoers_audit" plugin, not
+ "sudoers_policy". This is because the sudoers file is now
+ opened and parsed by the "sudoers_audit" plugin. Previously,
+ this was done by the "sudoers_policy" plugin. The use of an
+ audit plugin makes it possible for the sudoers module to detect
+ when a command has been rejected by an approval plugin and only
+ log commands that are allowed by both policy and approval
+ plugins.
+
+o Upgrading from a version prior to 1.8.30:
+
+ Starting with version 1.8.30, sudo will no longer allow commands
+ to be run as a user or group ID that is not in the password or
+ group databases by default. Previously, sudo would always allow
+ unknown user or group IDs if the sudoers entry permitted it,
+ including via the "ALL" alias. The old behavior can be restored
+ by setting the new "allow_unknown_runas_id" Defaults setting
+ in the sudoers file.
+
+o Upgrading from a version prior to 1.8.29:
+
+ Starting with version 1.8.29, if the umask is explicitly set
+ in sudoers, that value is used regardless of the umask specified
+ by PAM or login.conf. However, if the umask is not explicitly
+ set in sudoers, PAM or login.conf may now override the default
+ sudoers umask. Previously, the sudoers umask always overrode
+ the umask set by PAM, which was not the documented behavior.
+
+o Upgrading from a version prior to 1.8.28:
+
+ Starting with version 1.8.28, sudo stores the signal that caused
+ a command to be suspended or resumed as a string in the I/O log
+ timing file. The version of sudoreplay included with sudo
+ 1.8.28 can process either type of I/O log file but older versions
+ of sudoreplay are unable to replay the newer logs.
+
+ Starting with version 1.8.28, sudoedit honors the umask and
+ umask_override settings in sudoers. Previously, the user's
+ umask was used as-is.
+
+o Upgrading from a version prior to 1.8.26:
+
+ Starting with version 1.8.26, sudo no long sets the USERNAME
+ environment variable when running commands. This is a non-standard
+ environment variable that was set on some older Linux systems.
+ Sudo still sets the LOGNAME, USER and, on AIX systems, LOGIN
+ environment variables.
+
+ Handling of the LOGNAME, USER (and on AIX, LOGIN) environment
+ variables has changed slightly in version 1.8.26. Sudo now
+ treats those variables as a single unit. This means that if
+ one variable is preserved or removed from the environment using
+ env_keep, env_check or env_delete, the others are too.
+
+o Upgrading from a version prior to 1.8.23:
+
+ In sudo 1.8.23 the "sudoers2ldif" script and the "visudo -x"
+ functionality has been superseded by the "cvtsudoers" utility.
+ The cvtsudoers utility is intended to be a drop-in replacement
+ for "sudoers2ldif". Because it uses the same parser as sudo
+ and visudo, cvtsudoers can perform a more accurate conversion
+ than sudoers2ldif could.
+
+ To convert a sudoers file to JSON, the format option must be
+ specified. For example, instead of:
+
+ visudo -f sudoers_file -x output_file
+
+ one would use:
+
+ cvtsudoers -f json -o output_file sudoers_file
+
+ Note that unlike "visudo -x", "cvtsudoers" reads from the
+ standard input by default. Also, the base DN may be specified
+ on the command line, if desired, using the -b option.
+
+o Upgrading from a version prior to 1.8.20:
+
+ Due to the addition of the TIMEOUT, NOTBEFORE and NOTAFTTER
+ options, it is no longer possible to declare an alias with one
+ of those names. If a sudoers file has an alias with one of
+ those names, sudo and visudo will report a syntax error with a
+ message like "syntax error: unexpected TIMEOUT, expecting ALIAS".
+
+ Starting with version 1.9.3, sudoers rules must end in either
+ Prior to version 1.8.20, when log_input, log_output or use_pty
+ were enabled, if any of the standard input, output or error
+ were not connected to a terminal, sudo would use a pipe. The
+ pipe allows sudo to interpose itself between the old standard
+ input, output or error and log the contents. Beginning with
+ version 1.8.20, a pipe is only used when I/O logging is enabled.
+ If use_pty is set without log_input or log_output, no pipe will
+ be used. Additionally, if log_input is set without log_output,
+ a pipe is only used for the standard input. Likewise, if
+ log_output is set without log_input, a pipe is only used for
+ the standard output and standard error. This results in a
+ noticeable change in behavior if the use_pty flag is set and no
+ terminal is present when running commands such as scripts that
+ execute other commands asynchronously (in the background).
+ Previously, sudo would exit immediately, causing background
+ commands to terminate with a broken pipe if they attempt to
+ write to the standard output or standard error. As of version
+ 1.8.20, a pipe will not be used in this case so the command
+ will no longer be terminated.
+
+o Upgrading from a version prior to 1.8.16:
+
+ When editing files with sudoedit, files in a directory that is
+ writable by the invoking user may no longer be edited by default.
+ Also, sudoedit will refuse to follow a symbolic link in the
+ path to be edited if that directory containing the link is
+ writable by the user. This behavior can be disabled by negating
+ the sudoedit_checkdir sudoers option, which is now enabled by
+ default.
+
+o Upgrading from a version prior to 1.8.15:
+
+ Prior to version 1.8.15, when env_reset was enabled (the default)
+ and the -s option was not used, the SHELL environment variable
+ was set to the shell of the invoking user. In 1.8.15 and above,
+ when env_reset is enabled and the -s option is not used, SHELL
+ is set based on the target user.
+
+ When editing files with sudoedit, symbolic links will no longer
+ be followed by default. The old behavior can be restored by
+ enabling the sudoedit_follow option in sudoers or on a per-command
+ basis with the FOLLOW and NOFOLLOW tags.
+
+ Prior to version 1.8.15, groups listed in sudoers that were not
+ found in the system group database were passed to the group
+ plugin, if any. Starting with 1.8.15, only groups of the form
+ %:group are resolved via the group plugin by default. The old
+ behavior can be restored by using the always_query_group_plugin
+ sudoers option.
+
+ Locking of the time stamp file has changed in sudo 1.8.15.
+ Previously, the user's entire time stamp file was locked while
+ retrieving and updating a time stamp record. Now, only a single
+ record, specific to the tty or parent process ID, is locked.
+ This lock is held while the user enters their password. If
+ sudo is suspended at the password prompt (or run in the
+ background), the lock is dropped until sudo is resumed, at which
+ point it will be reacquired. This allows sudo to be used in a
+ pipeline even when a password is required--only one instance
+ of sudo will prompt for a password.
+
+o Upgrading from a version prior to 1.8.14:
+
+ On HP-UX, sudo will no longer check for "plugin.sl" if "plugin.so"
+ is specified but does not exist. This was a temporary hack for
+ backward compatibility with Sudo 1.8.6 and below when the
+ plugin path name was not listed in sudo.conf. A plugin path
+ name that explicitly ends in ".sl" will still work as expected.
+
+o Upgrading from a version prior to 1.8.12:
+
+ On Solaris, sudo is now able to determine the NIS domain name.
+ As a result, if you had previously been using netgroups that
+ do not include the domain, you will need to either set the
+ domain in the entry or leave the domain part of the tuple blank.
+
+ For example, the following will no longer work:
+ my-hosts (foo,-,-) (bar,-,-) (baz,-,-)
+ and should be changed to:
+ my-hosts (foo,-,) (bar,-,) (baz,-,)
+
+o Upgrading from a version prior to 1.8.10:
+
+ The time stamp file format has changed in sudo 1.8.10. There
+ is now a single time stamp file for each user, even when tty-based
+ time stamps are used. Each time stamp file may contain multiple
+ records to support tty-based time stamps as well as multiple
+ authentication users. On systems that support it, monotonic
+ time is stored instead of wall clock time. As a result, it is
+ important that the time stamp files not persist when the system
+ reboots. For this reason, the default location for the time
+ stamp files has changed back to a directory located in /var/run.
+ Systems that do not have /var/run (e.g. AIX) or that do not clear
+ it on boot (e.g. HP-UX) will need to clear the time stamp
+ directory via a start up script. Such a script is installed by
+ default on AIX and HP-UX systems.
+
+ Because there is now a single time stamp file per user, the -K
+ option will remove all of the user's time stamps, not just the
+ time stamp for the current terminal.
+
+ Lecture status is now stored separately from the time stamps
+ in a separate directory: /var/db/sudo/lectured, /var/lib/sudo/lectured
+ or /var/adm/sudo/lectured depending on what is present on the
+ system.
+
+ LDAP-based sudoers now uses a default search filter of
+ (objectClass=sudoRole) for more efficient queries. It is
+ possible to disable the default search filter by specifying
+ SUDOERS_SEARCH_FILTER in ldap.conf but omitting a value.
+
+o Upgrading from a version prior to 1.8.7:
+
+ Sudo now stores its libexec files in a "sudo" sub-directory
+ instead of in libexec itself. For backward compatibility, if
+ the plugin is not found in the default plugin directory, sudo
+ will check the parent directory default directory ends in "/sudo".
+
+ The default sudo plugins now all use the .so extension, regardless
+ of the extension used by system shared libraries. For backward
+ compatibility, sudo on HP-UX will also search for a plugin with
+ an .sl extension if the .so version is not found.
+
+ Handling of users belonging to a large number of groups has
+ changed. Previously, sudo would only use the group list from
+ the kernel unless the system_group plugin was enabled in sudoers.
+ Now, sudo will query the groups database if the user belongs
+ to the maximum number of groups supported by the kernel. See
+ the group_source and max_groups settings in the sudo.conf manual
+ for details.
+
+o Upgrading from a version prior to 1.8.2:
+
+ When matching Unix groups in the sudoers file, sudo will now
+ match based on the name of the group as it appears in sudoers
+ instead of the group-ID. This can substantially reduce the
+ number of group lookups for sudoers files that contain a large
+ number of groups. There are a few side effects of this change.
+
+ 1) Unix groups with different names but the same group-ID are
+ can no longer be used interchangeably. Sudo will look up all
+ of a user's groups by group-ID and use the resulting group
+ names when matching sudoers entries. If there are multiple
+ groups with the same ID, the group name returned by the
+ system getgrgid() library function is the name that will be
+ used when matching sudoers entries.
+
+ 2) Unix group names specified in the sudoers file that are
+ longer than the system maximum will no longer match. For
+ instance, if there is a Unix group "fireflie" on a system
+ where group names are limited to eight characters, "%fireflies"
+ in sudoers will no longer match "fireflie". Previously, a
+ lookup by name of the group "fireflies" would have matched
+ the "fireflie" group on most systems.
+
+ The legacy group matching behavior may be restored by enabling
+ the match_group_by_gid Defaults option in sudoers available
+ in sudo 1.8.18 and higher.
+
+o Upgrading from a version prior to 1.8.1:
+
+ Changes in the sudoers parser could result in parse errors for
+ existing sudoers file. These changes cause certain erroneous
+ entries to be flagged as errors where before they allowed.
+ Changes include:
+
+ Combining multiple Defaults entries with a backslash. E.g.
+
+ Defaults set_path \
+ Defaults syslog
+
+ which should be:
+
+ Defaults set_path
+ Defaults syslog
+
+ Also, double-quoted strings with a missing end-quote are now
+ detected and result in an error. Previously, text starting a
+ double quote and ending with a newline was ignored. E.g.
+
+ Defaults set_path"foo
+
+ In previous versions of sudo, the `"foo' portion would have
+ been ignored.
+
+ To avoid problems, sudo 1.8.1's "make install" will not install
+ a new sudo binary if the existing sudoers file has errors.
+
+ In Sudo 1.8.1 the "noexec" functionality has moved out of the
+ sudoers policy plugin and into the sudo front-end. As a result,
+ the path to the noexec file is now specified in the sudo.conf
+ file instead of the sudoers file. If you have a sudoers file
+ that uses the "noexec_file" option, you will need to move the
+ definition to the sudo.conf file instead.
+
+ Old style in /etc/sudoers:
+ Defaults noexec_file=/usr/local/libexec/sudo_noexec.so
+
+ New style in /etc/sudo.conf:
+ Path noexec /usr/local/libexec/sudo_noexec.so
+
+o Upgrading from a version prior to 1.8.0:
+
+ Starting with version 1.8.0, sudo uses a modular framework to
+ support policy and I/O logging plugins. The default policy
+ plugin is "sudoers" which provides the traditional sudoers
+ evaluation and I/O logging. Plugins are typically located in
+ /usr/libexec or /usr/local/libexec, though this is system-dependent.
+ The sudoers plugin is named "sudoers.so" on most systems.
+
+ The sudo.conf file, usually stored in /etc, is used to configure
+ plugins. This file is optional--if no plugins are specified
+ in sudo.conf, the "sudoers" plugin is used. See the example
+ sudo.conf file in the doc directory or refer to the updated
+ sudo manual to see how to configure sudo.conf.
+
+ The "askpass" setting has moved from the sudoers file to the
+ sudo.conf file. If you have a sudoers file that uses the
+ "askpass" option, you will need to move the definition to the
+ sudo.conf file.
+
+ Old style in /etc/sudoers:
+ Defaults askpass=/usr/X11R6/bin/ssh-askpass
+
+ New style in /etc/sudo.conf:
+ Path askpass /usr/X11R6/bin/ssh-askpass
+
+o Upgrading from a version prior to 1.7.5:
+
+ Sudo 1.7.5 includes an updated LDAP schema with support for
+ the sudoNotBefore, sudoNotAfter and sudoOrder attributes.
+
+ The sudoNotBefore and sudoNotAfter attribute support is only
+ used when the SUDOERS_TIMED setting is enabled in ldap.conf.
+ If enabled, those attributes are used directly when constructing
+ an LDAP filter. As a result, your LDAP server must have the
+ updated schema if you want to use sudoNotBefore and sudoNotAfter.
+
+ The sudoOrder support does not affect the LDAP filter sudo
+ constructs and so there is no need to explicitly enable it in
+ ldap.conf. If the sudoOrder attribute is not present in an
+ entry, a value of 0 is used. If no entries contain sudoOrder
+ attributes, the results are in whatever order the LDAP server
+ returns them, as in past versions of sudo.
+
+ Older versions of sudo will simply ignore the new attributes
+ if they are present in an entry. There are no compatibility
+ problems using the updated schema with older versions of sudo.
+
+o Upgrading from a version prior to 1.7.4:
+
+ Starting with sudo 1.7.4, the time stamp files have moved from
+ /var/run/sudo to either /var/db/sudo, /var/lib/sudo or /var/adm/sudo.
+ The directories are checked for existence in that order. This
+ prevents users from receiving the sudo lecture every time the
+ system reboots. Time stamp files older than the boot time are
+ ignored on systems where it is possible to determine this.
+
+ Additionally, the tty_tickets sudoers option is now enabled by
+ default. To restore the old behavior (single time stamp per user),
+ add a line like:
+ Defaults !tty_tickets
+ to sudoers or use the --without-tty-tickets configure option.
+
+ The HOME and MAIL environment variables are now reset based on the
+ target user's password database entry when the env_reset sudoers option
+ is enabled (which is the case in the default configuration). Users
+ wishing to preserve the original values should use a sudoers entry like:
+ Defaults env_keep += HOME
+ to preserve the old value of HOME and
+ Defaults env_keep += MAIL
+ to preserve the old value of MAIL.
+
+ NOTE: preserving HOME has security implications since many programs
+ use it when searching for configuration files. Adding HOME to env_keep
+ may enable a user to run unrestricted commands via sudo.
+
+ The default syslog facility has changed from "local2" to "authpriv"
+ (or "auth" if the operating system doesn't have "authpriv").
+ The --with-logfac configure option can be used to change this
+ or it can be changed in the sudoers file.
+
+o Upgrading from a version prior to 1.7.0:
+
+ Starting with sudo 1.7.0, comments in the sudoers file must not
+ have a digit or minus sign immediately after the comment character
+ ('#'). Otherwise, the comment may be interpreted as a user or
+ group-ID.
+
+ When sudo is build with LDAP support the /etc/nsswitch.conf file is
+ now used to determine the sudoers sea ch order. sudo will default to
+ only using /etc/sudoers unless /etc/nsswitch.conf says otherwise.
+ This can be changed with an nsswitch.conf line, e.g.:
+ sudoers: ldap files
+ Would case LDAP to be searched first, then the sudoers file.
+ To restore the pre-1.7.0 behavior, run configure with the
+ --with-nsswitch=no flag.
+
+ Sudo now ignores user .ldaprc files as well as system LDAP defaults.
+ All LDAP configuration is now in /etc/ldap.conf (or whichever file
+ was specified by configure's --with-ldap-conf-file option).
+ If you are using TLS, you may now need to specify:
+ tls_checkpeer no
+ in sudo's ldap.conf unless ldap.conf references a valid certificate
+ authority file(s).
+
+ Please also see the NEWS file for a list of new features in
+ sudo 1.7.0.
+
+o Upgrading from a version prior to 1.6.9:
+
+ Starting with sudo 1.6.9, if an OS supports a modular authentication
+ method such as PAM, it will be used by default by configure.
+
+ Environment variable handling has changed significantly in sudo
+ 1.6.9. Prior to version 1.6.9, sudo would preserve the user's
+ environment, pruning out potentially dangerous variables.
+ Beginning with sudo 1.6.9, the environment is reset to a default
+ set of values with only a small number of "safe" variables
+ preserved. To preserve specific environment variables, add
+ them to the "env_keep" list in sudoers. E.g.
+
+ Defaults env_keep += "EDITOR"
+
+ The old behavior can be restored by negating the "env_reset"
+ option in sudoers. E.g.
+
+ Defaults !env_reset
+
+ There have also been changes to how the "env_keep" and
+ "env_check" options behave.
+
+ Prior to sudo 1.6.9, the TERM and PATH environment variables
+ would always be preserved even if the env_keep option was
+ redefined. That is no longer the case. Consequently, if
+ env_keep is set with "=" and not simply appended to (i.e. using
+ "+="), PATH and TERM must be explicitly included in the list
+ of environment variables to keep. The LOGNAME, SHELL, USER,
+ and USERNAME environment variables are still always set.
+
+ Additionally, the env_check setting previously had no effect
+ when env_reset was set (which is now on by default). Starting
+ with sudo 1.6.9, environment variables listed in env_check are
+ also preserved in the env_reset case, provided that they do not
+ contain a '/' or '%' character. Note that it is not necessary
+ to also list a variable in env_keep--having it in env_check is
+ sufficient.
+
+ The default lists of variables to be preserved and/or checked
+ are displayed when sudo is run by root with the -V flag.
+
+o Upgrading from a version prior to 1.6.8:
+
+ Prior to sudo 1.6.8, if /var/run did not exist, sudo would put
+ the time stamp files in /tmp/.odus. As of sudo 1.6.8, the
+ time stamp files will be placed in /var/adm/sudo or /usr/adm/sudo
+ if there is no /var/run directory. This directory will be
+ created if it does not already exist.
+
+ Previously, a sudoers entry that explicitly prohibited running
+ a command as a certain user did not override a previous entry
+ allowing the same command. This has been fixed in sudo 1.6.8
+ such that the last match is now used (as it is documented).
+ Hopefully no one was depending on the previous (buggy) behavior.
+
+o Upgrading from a version prior to 1.6:
+
+ As of sudo 1.6, parsing of runas entries and the NOPASSWD tag
+ has changed. Prior to 1.6, a runas specifier applied only to
+ a single command directly following it. Likewise, the NOPASSWD
+ tag only allowed the command directly following it to be run
+ without a password. Starting with sudo 1.6, both the runas
+ specifier and the NOPASSWD tag are "sticky" for an entire
+ command list. So, given the following line in sudo < 1.6
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami,/bin/ls
+
+ millert would be able to run /usr/bin/whoami as user daemon
+ without a password and /bin/ls as root with a password.
+
+ As of sudo 1.6, the same line now means that millert is able
+ to run run both /usr/bin/whoami and /bin/ls as user daemon
+ without a password. To expand on this, take the following
+ example:
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami, (root) /bin/ls, \
+ /sbin/dump
+
+ millert can run /usr/bin/whoami as daemon and /bin/ls and
+ /sbin/dump as root. No password need be given for either
+ command. In other words, the "(root)" sets the default runas
+ user to root for the rest of the list. If we wanted to require
+ a password for /bin/ls and /sbin/dump the line could be written
+ as:
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami, \
+ (root) PASSWD:/bin/ls, /sbin/dump
+
+ Additionally, sudo now uses a per-user time stamp directory
+ instead of a time stamp file. This allows tty time stamps to
+ simply be files within the user's time stamp dir. For the
+ default, non-tty case, the time stamp on the directory itself
+ is used.
+
+ Also, the temporary file used by visudo is now /etc/sudoers.tmp
+ since some versions of vipw on systems with shadow passwords use
+ /etc/stmp for the temporary shadow file.
+
+o Upgrading from a version prior to 1.5:
+
+ By default, sudo expects the sudoers file to be mode 0440 and
+ to be owned by user and group 0. This differs from version 1.4
+ and below which expected the sudoers file to be mode 0400 and
+ to be owned by root. Doing a `make install' will set the sudoers
+ file to the new mode and group. If sudo encounters a sudoers
+ file with the old permissions it will attempt to update it to
+ the new scheme. You cannot, however, use a sudoers file with
+ the new permissions with an old sudo binary. It is suggested
+ that if have a means of distributing sudo you distribute the
+ new binaries first, then the new sudoers file (or you can leave
+ sudoers as is and sudo will fix the permissions itself as long
+ as sudoers is on a local file system).
diff --git a/doc/cvtsudoers.man.in b/doc/cvtsudoers.man.in
new file mode 100644
index 0000000..f1a8e91
--- /dev/null
+++ b/doc/cvtsudoers.man.in
@@ -0,0 +1,513 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2018 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.
+.\"
+.TH "CVTSUDOERS" "1" "December 11, 2018" "Sudo @PACKAGE_VERSION@" "General Commands Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBcvtsudoers\fR
+\- convert between sudoers file formats
+.SH "SYNOPSIS"
+.HP 11n
+\fBcvtsudoers\fR
+[\fB\-ehMpV\fR]
+[\fB\-b\fR\ \fIdn\fR]
+[\fB\-c\fR\ \fIconf_file\fR]
+[\fB\-d\fR\ \fIdeftypes\fR]
+[\fB\-f\fR\ \fIoutput_format\fR]
+[\fB\-i\fR\ \fIinput_format\fR]
+[\fB\-I\fR\ \fIincrement\fR]
+[\fB\-m\fR\ \fIfilter\fR]
+[\fB\-o\fR\ \fIoutput_file\fR]
+[\fB\-O\fR\ \fIstart_point\fR]
+[\fB\-P\fR\ \fIpadding\fR]
+[\fB\-s\fR\ \fIsections\fR]
+[\fIinput_file\fR]
+.SH "DESCRIPTION"
+\fBcvtsudoers\fR
+can be used to convert between
+\fIsudoers\fR
+security policy file formats.
+The default input format is sudoers.
+The default output format is LDIF.
+It is only possible to convert a
+\fIsudoers\fR
+file that is syntactically correct.
+.PP
+If no
+\fIinput_file\fR
+is specified, or if it is
+\(oq-\(cq,
+the policy is read from the standard input.
+By default, the result is written to the standard output.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-b\fR \fIdn\fR, \fB\--base\fR=\fIdn\fR
+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.
+If this option is not specified, the value of the
+\fRSUDOERS_BASE\fR
+environment variable will be used instead.
+Only necessary when converting to LDIF format.
+.TP 12n
+\fB\-c\fR \fIconf_file\fR, \fB\--config\fR=\fIconf_file\fR
+Specify the path to the configuration file.
+Defaults to
+\fI@sysconfdir@/cvtsudoers.conf\fR.
+.TP 12n
+\fB\-d\fR \fIdeftypes\fR, \fB\--defaults\fR=\fIdeftypes\fR
+Only convert
+\fRDefaults\fR
+entries of the specified types.
+One or more
+\fRDefaults\fR
+types may be specified, separated by a comma
+(\(oq\&,\(cq).
+The supported types are:
+.PP
+.RS 12n
+.PD 0
+.TP 10n
+all
+All Defaults entries.
+.PD
+.TP 10n
+global
+Global Defaults entries that are applied regardless of
+user, runas, host or command.
+.TP 10n
+user
+Per-user Defaults entries.
+.TP 10n
+runas
+Per-runas user Defaults entries.
+.TP 10n
+host
+Per-host Defaults entries.
+.TP 10n
+command
+Per-command Defaults entries.
+.PP
+See the
+\fBDefaults\fR
+section in
+sudoers(@mansectform@)
+for more information.
+.sp
+If the
+\fB\-d\fR
+option is not specified, all
+\fRDefaults\fR
+entries will be converted.
+.RE
+.TP 12n
+\fB\-e\fR, \fB\--expand-aliases\fR
+Expand aliases in
+\fIinput_file\fR.
+Aliases are preserved by default when the output
+\fIformat\fR
+is JSON or sudoers.
+.TP 12n
+\fB\-f\fR \fIoutput_format\fR, \fB\--output-format\fR=\fIoutput_format\fR
+Specify the output format (case-insensitive).
+The following formats are supported:
+.PP
+.RS 12n
+.PD 0
+.TP 10n
+JSON
+JSON (JavaScript Object Notation) files are usually easier for
+third-party applications to consume than the traditional
+\fIsudoers\fR
+format.
+The various values have explicit types which removes much of the
+ambiguity of the
+\fIsudoers\fR
+format.
+.PD
+.TP 10n
+LDIF
+LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
+server for use with
+sudoers.ldap(@mansectform@).
+.sp
+Conversion to LDIF has the following limitations:
+.PP
+.RS 10n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+Command, host, runas and user-specific Defaults lines cannot be
+translated as they don't have an equivalent in the sudoers LDAP schema.
+.PD
+.TP 3n
+\fB\(bu\fR
+Command, host, runas and user aliases are not supported by the
+sudoers LDAP schema so they are expanded during the conversion.
+.PD 0
+.PP
+.RE
+.PD
+.TP 10n
+sudoers
+Traditional sudoers format.
+A new sudoers file will be reconstructed from the parsed input file.
+Comments are not preserved and data from any include files will be
+output inline.
+.PD 0
+.PP
+.RE
+.PD
+.TP 12n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-i\fR \fIinput_format\fR, \fB\--input-format\fR=\fIinput_format\fR
+Specify the input format.
+The following formats are supported:
+.PP
+.RS 12n
+.PD 0
+.TP 10n
+LDIF
+LDIF (LDAP Data Interchange Format) files can be exported from an LDAP
+server to convert security policies used by
+sudoers.ldap(@mansectform@).
+If a base DN (distinguished name) is specified, only sudoRole objects
+that match the base DN will be processed.
+Not all sudoOptions specified in a sudoRole can be translated from
+LDIF to sudoers format.
+.PD
+.TP 10n
+sudoers
+Traditional sudoers format.
+This is the default input format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 12n
+\fB\-I\fR \fIincrement\fR, \fB\--increment\fR=\fIincrement\fR
+When generating LDIF output, increment each sudoOrder attribute by
+the specified number.
+Defaults to an increment of 1.
+.TP 12n
+\fB\-m\fR \fIfilter\fR, \fB\--match\fR=\fIfilter\fR
+Only output rules that match the specified
+\fIfilter\fR.
+A
+\fIfilter\fR
+expression is made up of one or more
+\fBkey =\fR \fIvalue\fR
+pairs, separated by a comma
+(\(oq\&,\(cq).
+The
+\fBkey\fR
+may be
+\(lquser\(rq,
+\(lqgroup\(rq
+or
+\(lqhost\(rq.
+For example,
+\fBuser\fR = \fIoperator\fR
+or
+\fBhost\fR = \fIwww\fR.
+An upper-case User_Alias or Host_Alias may be specified as the
+\(lquser\(rq
+or
+\(lqhost\(rq.
+.sp
+A matching
+\fIsudoers\fR
+rule may also include users, groups and hosts that are not part of the
+\fIfilter\fR.
+This can happen when a rule includes multiple users, groups or hosts.
+To prune out any non-matching user, group or host from the rules, the
+\fB\-p\fR
+option may be used.
+.sp
+By default, the password and group databases are not consulted when matching
+against the filter so the users and groups do not need to be present
+on the local system (see the
+\fB\-M\fR
+option).
+Only aliases that are referenced by the filtered policy rules will
+be displayed.
+.TP 12n
+\fB\-M\fR, \fB\--match-local\fR
+When the
+\fB\-m\fR
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+\fB\-M\fR
+is
+\fInot\fR
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
+.TP 12n
+\fB\-o\fR \fIoutput_file\fR, \fB\--output\fR=\fIoutput_file\fR
+Write the converted output to
+\fIoutput_file\fR.
+If no
+\fIoutput_file\fR
+is specified, or if it is
+\(oq-\(cq,
+the converted
+\fIsudoers\fR
+policy will be written to the standard output.
+.TP 12n
+\fB\-O\fR \fIstart_point\fR, \fB\--order-start\fR=\fIstart_point\fR
+When generating LDIF output, use the number specified by
+\fIstart_point\fR
+in the sudoOrder attribute of the first sudoRole object.
+Subsequent sudoRole object use a sudoOrder value generated by adding an
+\fIincrement\fR,
+see the
+\fB\-I\fR
+option for details.
+Defaults to a starting point of 1.
+A starting point of 0 will disable the generation of sudoOrder
+attributes in the resulting LDIF file.
+.TP 12n
+\fB\-p\fR, \fB\--prune-matches\fR
+When the
+\fB\-m\fR
+option is also specified,
+\fBcvtsudoers\fR
+will prune out non-matching users, groups and hosts from
+matching entries.
+.TP 12n
+\fB\-P\fR \fIpadding\fR, \fB\--padding\fR=\fIpadding\fR
+When generating LDIF output, construct the initial sudoOrder value by
+concatenating
+\fIorder_start\fR
+and
+\fIincrement\fR,
+padding the
+\fIincrement\fR
+with zeros until it consists of
+\fIpadding\fR
+digits.
+For example, if
+\fIorder_start\fR
+is 1027,
+\fIpadding\fR
+is 3, and
+\fIincrement\fR
+is 1, the value of sudoOrder for the first entry will be 1027000,
+followed by 1027001, 1027002, etc.
+If the number of sudoRole entries is larger than the padding would allow,
+\fBcvtsudoers\fR
+will exit with an error.
+By default, no padding is performed.
+.TP 12n
+\fB\-s\fR \fIsections\fR, \fB\--suppress\fR=\fIsections\fR
+Suppress the output of specific
+\fIsections\fR
+of the security policy.
+One or more section names may be specified, separated by a comma
+(\(oq\&,\(cq).
+The supported section name are:
+\fBdefaults\fR,
+\fBaliases\fR
+and
+\fBprivileges\fR
+(which may be shortened to
+\fBprivs\fR).
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBcvtsudoers\fR
+and
+\fIsudoers\fR
+grammar versions and exit.
+.PP
+Options in the form
+\(lqkeyword = value\(rq
+may also be specified in a configuration file,
+\fI@sysconfdir@/cvtsudoers.conf\fR
+by default.
+The following keywords are recognized:
+.TP 6n
+\fBdefaults =\fR \fIdeftypes\fR
+See the description of the
+\fB\-d\fR
+command line option.
+.TP 6n
+\fBexpand_aliases =\fR \fIyes\fR | \fIno\fR
+See the description of the
+\fB\-e\fR
+command line option.
+.TP 6n
+\fBinput_format =\fR \fIldif\fR | \fIsudoers\fR
+See the description of the
+\fB\-i\fR
+command line option.
+.TP 6n
+\fBmatch =\fR \fIfilter\fR
+See the description of the
+\fB\-m\fR
+command line option.
+.TP 6n
+\fBorder_increment =\fR \fIincrement\fR
+See the description of the
+\fB\-I\fR
+command line option.
+.TP 6n
+\fBorder_start =\fR \fIstart_point\fR
+See the description of the
+\fB\-O\fR
+command line option.
+.TP 6n
+\fBoutput_format =\fR \fIjson\fR | \fIldif\fR | \fIsudoers\fR
+See the description of the
+\fB\-f\fR
+command line option.
+.TP 6n
+\fBpadding =\fR \fIpadding\fR
+See the description of the
+\fB\-P\fR
+command line option.
+.TP 6n
+\fBprune_matches =\fR \fIyes\fR | \fIno\fR
+See the description of the
+\fB\-p\fR
+command line option.
+.TP 6n
+\fBsudoers_base =\fR \fIdn\fR
+See the description of the
+\fB\-b\fR
+command line option.
+.TP 6n
+\fBsuppress =\fR \fIsections\fR
+See the description of the
+\fB\-s\fR
+command line option.
+.PP
+Options on the command line will override values from the
+configuration file.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/cvtsudoers.conf\fR
+default configuration for cvtsudoers
+.SH "EXAMPLES"
+Convert
+\fI/etc/sudoers\fR
+to LDIF (LDAP Data Interchange Format) where the
+\fIldap.conf\fR
+file uses a
+\fIsudoers_base\fR
+of my-domain,dc=com, storing the result in
+\fIsudoers.ldif\fR:
+.nf
+.sp
+.RS 6n
+$ cvtsudoers -b ou=SUDOers,dc=my-domain,dc=com -o sudoers.ldif \e
+ /etc/sudoers
+.RE
+.fi
+.PP
+Convert
+\fI/etc/sudoers\fR
+to JSON format, storing the result in
+\fIsudoers.json\fR:
+.nf
+.sp
+.RS 6n
+$ cvtsudoers -f json -o sudoers.json /etc/sudoers
+.RE
+.fi
+.PP
+Parse
+\fI/etc/sudoers\fR
+and display only rules that match user
+\fIambrose\fR
+on host
+\fIhastur\fR:
+.nf
+.sp
+.RS 6n
+$ cvtsudoers -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.RE
+.fi
+.PP
+Same as above, but expand aliases and prune out any non-matching
+users and hosts from the expanded entries.
+.nf
+.sp
+.RS 6n
+$ cvtsudoers -ep -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.RE
+.fi
+.PP
+Convert
+\fIsudoers.ldif\fR
+from LDIF to traditional
+\fIsudoers\fR
+format:
+.nf
+.sp
+.RS 6n
+$ cvtsudoers -i ldif -f sudoers -o sudoers.new sudoers.ldif
+.RE
+.fi
+.SH "SEE ALSO"
+sudoers(@mansectform@),
+sudoers.ldap(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBcvtsudoers\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBcvtsudoers\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/cvtsudoers.mdoc.in b/doc/cvtsudoers.mdoc.in
new file mode 100644
index 0000000..b24f363
--- /dev/null
+++ b/doc/cvtsudoers.mdoc.in
@@ -0,0 +1,439 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2018 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.
+.\"
+.Dd December 11, 2018
+.Dt CVTSUDOERS 1
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm cvtsudoers
+.Nd convert between sudoers file formats
+.Sh SYNOPSIS
+.Nm cvtsudoers
+.Op Fl ehMpV
+.Op Fl b Ar dn
+.Op Fl c Ar conf_file
+.Op Fl d Ar deftypes
+.Op Fl f Ar output_format
+.Op Fl i Ar input_format
+.Op Fl I Ar increment
+.Op Fl m Ar filter
+.Op Fl o Ar output_file
+.Op Fl O Ar start_point
+.Op Fl P Ar padding
+.Op Fl s Ar sections
+.Op Ar input_file
+.Sh DESCRIPTION
+.Nm
+can be used to convert between
+.Em sudoers
+security policy file formats.
+The default input format is sudoers.
+The default output format is LDIF.
+It is only possible to convert a
+.Em sudoers
+file that is syntactically correct.
+.Pp
+If no
+.Ar input_file
+is specified, or if it is
+.Ql - ,
+the policy is read from the standard input.
+By default, the result is written to the standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl b Ar dn , Fl -base Ns = Ns Ar dn
+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 .
+If this option is not specified, the value of the
+.Ev SUDOERS_BASE
+environment variable will be used instead.
+Only necessary when converting to LDIF format.
+.It Fl c Ar conf_file , Fl -config Ns = Ns Ar conf_file
+Specify the path to the configuration file.
+Defaults to
+.Pa @sysconfdir@/cvtsudoers.conf .
+.It Fl d Ar deftypes , Fl -defaults Ns = Ns Ar deftypes
+Only convert
+.Li Defaults
+entries of the specified types.
+One or more
+.Li Defaults
+types may be specified, separated by a comma
+.Pq Ql \&, .
+The supported types are:
+.Bl -tag -width 8n
+.It all
+All Defaults entries.
+.It global
+Global Defaults entries that are applied regardless of
+user, runas, host or command.
+.It user
+Per-user Defaults entries.
+.It runas
+Per-runas user Defaults entries.
+.It host
+Per-host Defaults entries.
+.It command
+Per-command Defaults entries.
+.El
+.Pp
+See the
+.Sy Defaults
+section in
+.Xr sudoers @mansectform@
+for more information.
+.Pp
+If the
+.Fl d
+option is not specified, all
+.Li Defaults
+entries will be converted.
+.It Fl e , Fl -expand-aliases
+Expand aliases in
+.Ar input_file .
+Aliases are preserved by default when the output
+.Ar format
+is JSON or sudoers.
+.It Fl f Ar output_format , Fl -output-format Ns = Ns Ar output_format
+Specify the output format (case-insensitive).
+The following formats are supported:
+.Bl -tag -width 8n
+.It JSON
+JSON (JavaScript Object Notation) files are usually easier for
+third-party applications to consume than the traditional
+.Em sudoers
+format.
+The various values have explicit types which removes much of the
+ambiguity of the
+.Em sudoers
+format.
+.It LDIF
+LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
+server for use with
+.Xr sudoers.ldap @mansectform@ .
+.Pp
+Conversion to LDIF has the following limitations:
+.Bl -bullet -width 1n
+.It
+Command, host, runas and user-specific Defaults lines cannot be
+translated as they don't have an equivalent in the sudoers LDAP schema.
+.It
+Command, host, runas and user aliases are not supported by the
+sudoers LDAP schema so they are expanded during the conversion.
+.El
+.It sudoers
+Traditional sudoers format.
+A new sudoers file will be reconstructed from the parsed input file.
+Comments are not preserved and data from any include files will be
+output inline.
+.El
+.It Fl h , Fl -help
+Display a short help message to the standard output and exit.
+.It Fl i Ar input_format , Fl -input-format Ns = Ns Ar input_format
+Specify the input format.
+The following formats are supported:
+.Bl -tag -width 8n
+.It LDIF
+LDIF (LDAP Data Interchange Format) files can be exported from an LDAP
+server to convert security policies used by
+.Xr sudoers.ldap @mansectform@ .
+If a base DN (distinguished name) is specified, only sudoRole objects
+that match the base DN will be processed.
+Not all sudoOptions specified in a sudoRole can be translated from
+LDIF to sudoers format.
+.It sudoers
+Traditional sudoers format.
+This is the default input format.
+.El
+.It Fl I Ar increment , Fl -increment Ns = Ns Ar increment
+When generating LDIF output, increment each sudoOrder attribute by
+the specified number.
+Defaults to an increment of 1.
+.It Fl m Ar filter , Fl -match Ns = Ns Ar filter
+Only output rules that match the specified
+.Ar filter .
+A
+.Ar filter
+expression is made up of one or more
+.Sy key = Ar value
+pairs, separated by a comma
+.Pq Ql \&, .
+The
+.Sy key
+may be
+.Dq user ,
+.Dq group
+or
+.Dq host .
+For example,
+.Sy user No = Ar operator
+or
+.Sy host No = Ar www .
+An upper-case User_Alias or Host_Alias may be specified as the
+.Dq user
+or
+.Dq host .
+.Pp
+A matching
+.Em sudoers
+rule may also include users, groups and hosts that are not part of the
+.Ar filter .
+This can happen when a rule includes multiple users, groups or hosts.
+To prune out any non-matching user, group or host from the rules, the
+.Fl p
+option may be used.
+.Pp
+By default, the password and group databases are not consulted when matching
+against the filter so the users and groups do not need to be present
+on the local system (see the
+.Fl M
+option).
+Only aliases that are referenced by the filtered policy rules will
+be displayed.
+.It Fl M , Fl -match-local
+When the
+.Fl m
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+.Fl M
+is
+.Em not
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
+.It Fl o Ar output_file , Fl -output Ns = Ns Ar output_file
+Write the converted output to
+.Ar output_file .
+If no
+.Ar output_file
+is specified, or if it is
+.Ql - ,
+the converted
+.Em sudoers
+policy will be written to the standard output.
+.It Fl O Ar start_point , Fl -order-start Ns = Ns Ar start_point
+When generating LDIF output, use the number specified by
+.Ar start_point
+in the sudoOrder attribute of the first sudoRole object.
+Subsequent sudoRole object use a sudoOrder value generated by adding an
+.Ar increment ,
+see the
+.Fl I
+option for details.
+Defaults to a starting point of 1.
+A starting point of 0 will disable the generation of sudoOrder
+attributes in the resulting LDIF file.
+.It Fl p , Fl -prune-matches
+When the
+.Fl m
+option is also specified,
+.Nm
+will prune out non-matching users, groups and hosts from
+matching entries.
+.It Fl P Ar padding , Fl -padding Ns = Ns Ar padding
+When generating LDIF output, construct the initial sudoOrder value by
+concatenating
+.Ar order_start
+and
+.Ar increment ,
+padding the
+.Ar increment
+with zeros until it consists of
+.Ar padding
+digits.
+For example, if
+.Ar order_start
+is 1027,
+.Ar padding
+is 3, and
+.Ar increment
+is 1, the value of sudoOrder for the first entry will be 1027000,
+followed by 1027001, 1027002, etc.
+If the number of sudoRole entries is larger than the padding would allow,
+.Nm
+will exit with an error.
+By default, no padding is performed.
+.It Fl s Ar sections , Fl -suppress Ns = Ns Ar sections
+Suppress the output of specific
+.Ar sections
+of the security policy.
+One or more section names may be specified, separated by a comma
+.Pq Ql \&, .
+The supported section name are:
+.Sy defaults ,
+.Sy aliases
+and
+.Sy privileges
+(which may be shortened to
+.Sy privs ) .
+.It Fl V , -version
+Print the
+.Nm
+and
+.Em sudoers
+grammar versions and exit.
+.El
+.Pp
+Options in the form
+.Dq keyword = value
+may also be specified in a configuration file,
+.Pa @sysconfdir@/cvtsudoers.conf
+by default.
+The following keywords are recognized:
+.Bl -tag -width 4n
+.It Sy defaults = Ar deftypes
+See the description of the
+.Fl d
+command line option.
+.It Sy expand_aliases = Ar yes | no
+See the description of the
+.Fl e
+command line option.
+.It Sy input_format = Ar ldif | sudoers
+See the description of the
+.Fl i
+command line option.
+.It Sy match = Ar filter
+See the description of the
+.Fl m
+command line option.
+.It Sy order_increment = Ar increment
+See the description of the
+.Fl I
+command line option.
+.It Sy order_start = Ar start_point
+See the description of the
+.Fl O
+command line option.
+.It Sy output_format = Ar json | ldif | sudoers
+See the description of the
+.Fl f
+command line option.
+.It Sy padding = Ar padding
+See the description of the
+.Fl P
+command line option.
+.It Sy prune_matches = Ar yes | no
+See the description of the
+.Fl p
+command line option.
+.It Sy sudoers_base = Ar dn
+See the description of the
+.Fl b
+command line option.
+.It Sy suppress = Ar sections
+See the description of the
+.Fl s
+command line option.
+.El
+.Pp
+Options on the command line will override values from the
+configuration file.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/cvtsudoers.conf
+default configuration for cvtsudoers
+.El
+.Sh EXAMPLES
+Convert
+.Pa /etc/sudoers
+to LDIF (LDAP Data Interchange Format) where the
+.Pa ldap.conf
+file uses a
+.Em sudoers_base
+of my-domain,dc=com, storing the result in
+.Pa sudoers.ldif :
+.Bd -literal -offset indent
+$ cvtsudoers -b ou=SUDOers,dc=my-domain,dc=com -o sudoers.ldif \e
+ /etc/sudoers
+.Ed
+.Pp
+Convert
+.Pa /etc/sudoers
+to JSON format, storing the result in
+.Pa sudoers.json :
+.Bd -literal -offset indent
+$ cvtsudoers -f json -o sudoers.json /etc/sudoers
+.Ed
+.Pp
+Parse
+.Pa /etc/sudoers
+and display only rules that match user
+.Em ambrose
+on host
+.Em hastur :
+.Bd -literal -offset indent
+$ cvtsudoers -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.Ed
+.Pp
+Same as above, but expand aliases and prune out any non-matching
+users and hosts from the expanded entries.
+.Bd -literal -offset indent
+$ cvtsudoers -ep -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.Ed
+.Pp
+Convert
+.Pa sudoers.ldif
+from LDIF to traditional
+.Em sudoers
+format:
+.Bd -literal -offset indent
+$ cvtsudoers -i ldif -f sudoers -o sudoers.new sudoers.ldif
+.Ed
+.Sh SEE ALSO
+.Xr sudoers @mansectform@ ,
+.Xr sudoers.ldap @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/fixman.sh b/doc/fixman.sh
new file mode 100755
index 0000000..c22b58c
--- /dev/null
+++ b/doc/fixman.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2012-2014, 2017 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.
+#
+
+OUTFILE="$1"
+rm -f "$OUTFILE"
+> "$OUTFILE"
+
+# HP-UX friendly header/footer for all man pages
+if [ X"`uname 2>&1`" = X"HP-UX" ]; then
+ cat >>"$OUTFILE" <<-'EOF'
+ s/^\.TH \("[^"]*"\) \("[^"]*"\) "\([^"]*\)" "\([^"]*\)" \("[^"]*"\)/.TH \1 \2\
+ .ds )H \4\
+ .ds ]W \3/
+EOF
+fi
+
+# Replace "0 minutes" with "unlimited"
+cat >>"$OUTFILE" <<-'EOF'
+ /^\\fR0\\fR$/ {
+ N
+ s/^\\fR0\\fR\nminutes\.$/unlimited./
+ }
+EOF
diff --git a/doc/fixmdoc.sed b/doc/fixmdoc.sed
new file mode 100644
index 0000000..3d57216
--- /dev/null
+++ b/doc/fixmdoc.sed
@@ -0,0 +1,5 @@
+# Replace "0 minutes" with "unlimited"
+/^\.Li 0$/ {
+ N
+ s/^\.Li 0\nminutes\.$/unlimited./
+}
diff --git a/doc/schema.ActiveDirectory b/doc/schema.ActiveDirectory
new file mode 100644
index 0000000..f488eef
--- /dev/null
+++ b/doc/schema.ActiveDirectory
@@ -0,0 +1,255 @@
+#
+# Active Directory Schema for sudo configuration (sudoers)
+#
+# To extend your Active Directory schema, run one of the following command
+# on your Windows DC (default port - Active Directory):
+#
+# ldifde -i -f schema.ActiveDirectory -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# or on your Windows DC if using another port (with Active Directory LightWeight Directory Services / ADAM-Active Directory Application Mode)
+# Port 50000 by example (or any other port specified when defining the ADLDS/ADAM instance
+#
+# ldifde -i -f schema.ActiveDirectory -t 50000 -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# or
+#
+# ldifde -i -f schema.ActiveDirectory -s server:port -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# Can add username domain and password
+#
+# -b username domain password
+#
+# Can create Log file in current or any directory
+#
+# -j .
+#
+
+dn: CN=sudoUser,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoUser
+distinguishedName: CN=sudoUser,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.1
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoUser
+adminDescription: User(s) who may run sudo
+oMSyntax: 22
+searchFlags: 1
+lDAPDisplayName: sudoUser
+name: sudoUser
+schemaIDGUID:: JrGcaKpnoU+0s+HgeFjAbg==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoHost,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoHost
+distinguishedName: CN=sudoHost,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.2
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoHost
+adminDescription: Host(s) who may run sudo
+oMSyntax: 22
+lDAPDisplayName: sudoHost
+name: sudoHost
+schemaIDGUID:: d0TTjg+Y6U28g/Y+ns2k4w==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoCommand
+distinguishedName: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.3
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoCommand
+adminDescription: Command(s) to be executed by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoCommand
+name: sudoCommand
+schemaIDGUID:: D6QR4P5UyUen3RGYJCHCPg==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAs
+distinguishedName: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.4
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAs
+adminDescription: User(s) impersonated by sudo (deprecated)
+oMSyntax: 22
+lDAPDisplayName: sudoRunAs
+name: sudoRunAs
+schemaIDGUID:: CP98mCQTyUKKxGrQeM80hQ==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoOption,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoOption
+distinguishedName: CN=sudoOption,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.5
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoOption
+adminDescription: Option(s) followed by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoOption
+name: sudoOption
+schemaIDGUID:: ojaPzBBlAEmsvrHxQctLnA==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAsUser
+distinguishedName: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.6
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAsUser
+adminDescription: User(s) impersonated by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoRunAsUser
+name: sudoRunAsUser
+schemaIDGUID:: 9C52yPYd3RG3jMR2VtiVkw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAsGroup
+distinguishedName: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.7
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAsGroup
+adminDescription: Groups(s) impersonated by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoRunAsGroup
+name: sudoRunAsGroup
+schemaIDGUID:: xJhSt/Yd3RGJPTB1VtiVkw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoNotBefore,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoNotBefore
+distinguishedName: CN=sudoNotBefore,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.8
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoNotBefore
+adminDescription: Start of time interval for which the entry is valid
+oMSyntax: 24
+lDAPDisplayName: sudoNotBefore
+name: sudoNotBefore
+schemaIDGUID:: dm1HnRfY4RGf4gopYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoNotAfter,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoNotAfter
+distinguishedName: CN=sudoNotAfter,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.9
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoNotAfter
+adminDescription: End of time interval for which the entry is valid
+oMSyntax: 24
+lDAPDisplayName: sudoNotAfter
+name: sudoNotAfter
+schemaIDGUID:: OAr/pBfY4RG9dBIpYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoOrder,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoOrder
+distinguishedName: CN=sudoOrder,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.10
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoOrder
+adminDescription: an integer to order the sudoRole entries
+oMSyntax: 2
+lDAPDisplayName: sudoOrder
+name: sudoOrder
+schemaIDGUID:: 0J8yrRfY4RGIYBUpYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn:
+changetype: modify
+add: schemaUpdateNow
+schemaUpdateNow: 1
+-
+
+dn: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: classSchema
+cn: sudoRole
+distinguishedName: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+possSuperiors: container
+possSuperiors: top
+subClassOf: top
+governsID: 1.3.6.1.4.1.15953.9.2.1
+mayContain: sudoCommand
+mayContain: sudoHost
+mayContain: sudoOption
+mayContain: sudoRunAs
+mayContain: sudoRunAsUser
+mayContain: sudoRunAsGroup
+mayContain: sudoUser
+mayContain: sudoNotBefore
+mayContain: sudoNotAfter
+mayContain: sudoOrder
+rDNAttID: cn
+showInAdvancedViewOnly: FALSE
+adminDisplayName: sudoRole
+adminDescription: Sudoer Entries
+objectClassCategory: 1
+lDAPDisplayName: sudoRole
+name: sudoRole
+schemaIDGUID:: SQn432lnZ0+ukbdh3+gN3w==
+systemOnly: FALSE
+objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=X
+defaultObjectCategory: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
diff --git a/doc/schema.OpenLDAP b/doc/schema.OpenLDAP
new file mode 100644
index 0000000..e1d525f
--- /dev/null
+++ b/doc/schema.OpenLDAP
@@ -0,0 +1,78 @@
+#
+# OpenLDAP schema file for Sudo
+# Save as /etc/openldap/schema/sudo.schema and restart slapd.
+# For a version that uses online configuration, see schema.olcSudo.
+#
+
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+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 )
+
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+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 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $
+ sudoNotAfter $ description )
+ )
diff --git a/doc/schema.iPlanet b/doc/schema.iPlanet
new file mode 100644
index 0000000..e512864
--- /dev/null
+++ b/doc/schema.iPlanet
@@ -0,0 +1,12 @@
+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.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.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 )
+objectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) X-ORIGIN 'SUDO' )
diff --git a/doc/schema.olcSudo b/doc/schema.olcSudo
new file mode 100644
index 0000000..8748dfc
--- /dev/null
+++ b/doc/schema.olcSudo
@@ -0,0 +1,79 @@
+dn: cn=sudoschema,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: sudoschema
+#
+# OpenLDAP schema file for Sudo in on-line configuration (OLC) format.
+# Import using ldapadd or another suitable LDAP browser.
+# Converted to OLC format by Frederic Pasteleurs <frederic@askarel.be>
+#
+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 )
+#
+olcattributetypes: ( 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 )
+#
+olcattributetypes: ( 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 )
+#
+olcattributetypes: ( 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 )
+#
+olcattributetypes: ( 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 )
+#
+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 )
+#
+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 )
+#
+olcattributetypes: ( 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 )
+#
+olcattributetypes: ( 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 )
+#
+olcattributeTypes: ( 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 )
+#
+olcobjectclasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $
+ description )
+ )
diff --git a/doc/sudo.conf.man.in b/doc/sudo.conf.man.in
new file mode 100644
index 0000000..36a3c00
--- /dev/null
+++ b/doc/sudo.conf.man.in
@@ -0,0 +1,864 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2010-2020 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.
+.\"
+.nr SL @SEMAN@
+.TH "SUDO.CONF" "@mansectform@" "December 5, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo.conf\fR
+\- configuration for sudo front end
+.SH "DESCRIPTION"
+The
+\fBsudo.conf\fR
+file is used to configure the
+\fBsudo\fR
+front end.
+It specifies the security policy and I/O logging plugins, debug flags
+as well as plugin-agnostic path names and settings.
+.PP
+The
+\fBsudo.conf\fR
+file supports the following directives, described in detail below.
+.TP 10n
+Plugin
+a security policy or I/O logging plugin
+.TP 10n
+Path
+a plugin-agnostic path
+.TP 10n
+Set
+a front end setting, such as
+\fIdisable_coredump\fR
+or
+\fIgroup_source\fR
+.TP 10n
+Debug
+debug flags to aid in debugging
+\fBsudo\fR,
+\fBsudoreplay\fR,
+\fBvisudo\fR,
+and the
+\fBsudoers\fR
+plugin.
+.PP
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+Note that leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.PP
+Non-comment lines that don't begin with
+\fRPlugin\fR,
+\fRPath\fR,
+\fRDebug\fR,
+or
+\fRSet\fR
+are silently ignored.
+.PP
+The
+\fBsudo.conf\fR
+file is always parsed in the
+\(lq\fRC\fR\(rq
+locale.
+.SS "Plugin configuration"
+\fBsudo\fR
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+\fBsudo\fR
+front end.
+Plugins are dynamically loaded based on the contents of
+\fBsudo.conf\fR.
+.PP
+A
+\fRPlugin\fR
+line consists of the
+\fRPlugin\fR
+keyword, followed by the
+\fIsymbol_name\fR
+and the
+\fIpath\fR
+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,
+or
+\fRpolicy_plugin\fR
+struct contained in the plugin.
+If a plugin implements multiple plugin types, there must be a
+\fRPlugin\fR
+line for each unique symbol name.
+The
+\fIpath\fR
+may be fully qualified or relative.
+If not fully qualified, it is relative to the directory
+specified by the
+\fIplugin_dir\fR
+\fRPath\fR
+setting, which defaults to
+\fI@plugindir@\fR.
+In other words:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy sudoers.so
+.RE
+.fi
+.PP
+is equivalent to:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy @plugindir@/sudoers.so
+.RE
+.fi
+.PP
+If the plugin was compiled statically into the
+\fBsudo\fR
+binary instead of being installed as a dynamic shared object, the
+\fIpath\fR
+should be specified without a leading directory,
+as it does not actually exist in the file system.
+For example:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy sudoers.so
+.RE
+.fi
+.PP
+Starting with
+\fBsudo\fR
+1.8.5, any additional parameters after the
+\fIpath\fR
+are passed as arguments to the plugin's
+\fIopen\fR
+function.
+For example, to override the compile-time default sudoers file mode:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy sudoers.so sudoers_mode=0440
+.RE
+.fi
+.PP
+See the
+sudoers(@mansectform@)
+manual for a list of supported arguments.
+.PP
+The same dynamic shared object may contain multiple plugins,
+each with a different symbol name.
+The file must be owned by uid 0 and only writable by its owner.
+Because of ambiguities that arise from composite policies, only a single
+policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+.PP
+If no
+\fBsudo.conf\fR
+file is present, or if it contains no
+\fRPlugin\fR
+lines, the
+\fBsudoers\fR
+plugin will be used as the default security policy, for I/O logging
+(if enabled by the policy) and for auditing.
+This is equivalent to the following:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+Plugin sudoers_audit sudoers.so
+.RE
+.fi
+.PP
+Starting with
+\fBsudo\fR
+version 1.9.1, some of the logging functionality of the
+\fBsudoers\fR
+plugin has been moved from the policy plugin to an audit plugin.
+To maintain compatibility with
+\fBsudo.conf\fR
+files from older
+\fBsudo\fR
+versions, if
+\fBsudoers\fR
+is configured as the security policy, it will be used as an audit
+plugin as well.
+This guarantees that the logging behavior will be consistnet with that of
+\fBsudo\fR
+versions 1.9.0 and below.
+.PP
+For more information on the
+\fBsudo\fR
+plugin architecture, see the
+sudo_plugin(@mansectform@)
+manual.
+.SS "Path settings"
+A
+\fRPath\fR
+line consists of the
+\fRPath\fR
+keyword, followed by the name of the path to set and its value.
+For example:
+.nf
+.sp
+.RS 6n
+Path noexec @noexec_file@
+Path askpass /usr/X11R6/bin/ssh-askpass
+.RE
+.fi
+.PP
+If no path name is specified, features relying on the specified
+setting will be disabled.
+Disabling
+\fRPath\fR
+settings is only supported in
+\fBsudo\fR
+version 1.8.16 and higher.
+.PP
+The following plugin-agnostic paths may be set in the
+\fI@sysconfdir@/sudo.conf\fR
+file:
+.TP 10n
+askpass
+The fully qualified path to a helper program used to read the user's
+password when no terminal is available.
+This may be the case when
+\fBsudo\fR
+is executed from a graphical (as opposed to text-based) application.
+The program specified by
+\fIaskpass\fR
+should display the argument passed to it as the prompt and write
+the user's password to the standard output.
+The value of
+\fIaskpass\fR
+may be overridden by the
+\fRSUDO_ASKPASS\fR
+environment variable.
+.TP 10n
+devsearch
+.br
+An ordered, colon-separated search path of directories to look in for
+device nodes.
+This is used when mapping the process's tty device number to a device name
+on systems that do not provide such a mechanism.
+Sudo will
+\fInot\fR
+recurse into sub-directories.
+If terminal devices may be located in a sub-directory of
+\fI/dev\fR,
+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
+.sp
+This option is ignored on systems that support either the
+\fBdevname\fR()
+or
+\fB_ttyname_dev\fR()
+functions, for example
+BSD,
+macOS and Solaris.
+.TP 10n
+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(),
+\fBexecvP\fR(),
+\fBexecvp\fR(),
+\fBexecvpe\fR(),
+\fBfexecve\fR(),
+\fBpopen\fR(),
+\fBposix_spawn\fR(),
+\fBposix_spawnp\fR(),
+\fBsystem\fR(),
+and
+\fBwordexp\fR()
+library functions that prevent the execution of further commands.
+This is used to implement the
+\fInoexec\fR
+functionality on systems that support
+\fRLD_PRELOAD\fR
+or its equivalent.
+The default value is
+\fI@noexec_file@\fR.
+.TP 10n
+plugin_dir
+The default directory to use when searching for plugins
+that are specified without a fully qualified path name.
+The default value is
+\fI@plugindir@\fR.
+.if \n(SL \{\
+.TP 10n
+sesh
+The fully-qualified path to the
+\fBsesh\fR
+binary.
+This setting is only used when
+\fBsudo\fR
+is built with SELinux support.
+The default value is
+\fI@sesh_file@\fR.
+.\}
+.SS "Other settings"
+The
+\fBsudo.conf\fR
+file also supports the following front end settings:
+.TP 10n
+disable_coredump
+Core dumps of
+\fBsudo\fR
+itself are disabled by default to prevent the disclosure of potentially
+sensitive information.
+To aid in debugging
+\fBsudo\fR
+crashes, you may wish to re-enable core dumps by setting
+\(lqdisable_coredump\(rq
+to false in
+\fBsudo.conf\fR
+as follows:
+.nf
+.sp
+.RS 16n
+Set disable_coredump false
+.RE
+.fi
+.RS 10n
+.sp
+All modern operating systems place restrictions on core dumps
+from set-user-ID processes like
+\fBsudo\fR
+so this option can be enabled without compromising security.
+To actually get a
+\fBsudo\fR
+core file you will likely need to enable core dumps for set-user-ID processes.
+On
+BSD
+and Linux systems this is accomplished in the
+sysctl(@mansectsu@)
+command.
+On Solaris, the
+coreadm(1m)
+command is used to configure core dump behavior.
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.4 and higher.
+.RE
+.TP 10n
+developer_mode
+By default
+\fBsudo\fR
+refuses to load plugins which can be modified by other than the root user.
+The plugin should be owned by root and write access permissions should be
+disabled for
+\(lqgroup\(rq
+and
+\(lqother\(rq\&.
+To make development of a plugin easier, you can disable that by setting
+\(lqdeveloper_mode\(rq
+option to true in
+\fBsudo.conf\fR
+as follows:
+.nf
+.sp
+.RS 16n
+Set developer_mode true
+.RE
+.fi
+.RS 10n
+.sp
+Please note that this creates a security risk, so it is not recommended
+on critical systems such as a desktop machine for daily use, but is intended
+to be used in development environments (VM, container, etc).
+Before enabling developer mode, ensure you understand the implications.
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.9.0 and higher.
+.RE
+.TP 10n
+group_source
+\fBsudo\fR
+passes the invoking user's group list to the policy and I/O plugins.
+On most systems, there is an upper limit to the number of groups that
+a user may belong to simultaneously (typically 16 for compatibility
+with NFS).
+On systems with the
+getconf(1)
+utility, running:
+.RS 16n
+getconf NGROUPS_MAX
+.RE
+.RS 10n
+will return the maximum number of groups.
+.sp
+However, it is still possible to be a member of a larger number of
+groups--they simply won't be included in the group list returned
+by the kernel for the user.
+Starting with
+\fBsudo\fR
+version 1.8.7, if the user's kernel group list has the maximum number
+of entries,
+\fBsudo\fR
+will consult the group database directly to determine the group list.
+This makes it possible for the security policy to perform matching by group
+name even when the user is a member of more than the maximum number of groups.
+.sp
+The
+\fIgroup_source\fR
+setting allows the administrator to change this default behavior.
+Supported values for
+\fIgroup_source\fR
+are:
+.TP 10n
+static
+Use the static group list that the kernel returns.
+Retrieving the group list this way is very fast but it is subject
+to an upper limit as described above.
+It is
+\(lqstatic\(rq
+in that it does not reflect changes to the group database made
+after the user logs in.
+This was the default behavior prior to
+\fBsudo\fR
+1.8.7.
+.TP 10n
+dynamic
+Always query the group database directly.
+It is
+\(lqdynamic\(rq
+in that changes made to the group database after the user logs in
+will be reflected in the group list.
+On some systems, querying the group database for all of a user's
+groups can be time consuming when querying a network-based group
+database.
+Most operating systems provide an efficient method of performing
+such queries.
+Currently,
+\fBsudo\fR
+supports efficient group queries on AIX,
+BSD,
+HP-UX, Linux and Solaris.
+.TP 10n
+adaptive
+Only query the group database if the static group list returned
+by the kernel has the maximum number of entries.
+This is the default behavior in
+\fBsudo\fR
+1.8.7 and higher.
+.PP
+For example, to cause
+\fBsudo\fR
+to only use the kernel's static list of groups for the user:
+.nf
+.sp
+.RS 16n
+Set group_source static
+.RE
+.fi
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.7 and higher.
+.RE
+.TP 10n
+max_groups
+The maximum number of user groups to retrieve from the group database.
+Values less than one will be ignored.
+This setting is only used when querying the group database directly.
+It is intended to be used on systems where it is not possible to detect
+when the array to be populated with group entries is not sufficiently large.
+By default,
+\fBsudo\fR
+will allocate four times the system's maximum number of groups (see above)
+and retry with double that number if the group database query fails.
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.7 and higher.
+It should not be required in
+\fBsudo\fR
+versions 1.8.24 and higher and may be removed in a later release.
+.TP 10n
+probe_interfaces
+By default,
+\fBsudo\fR
+will probe the system's network interfaces and pass the IP address
+of each enabled interface to the policy plugin.
+This makes it possible for the plugin to match rules based on the IP address
+without having to query DNS.
+On Linux systems with a large number of virtual interfaces, this may
+take a non-negligible amount of time.
+If IP-based matching is not required, network interface probing
+can be disabled as follows:
+.nf
+.sp
+.RS 16n
+Set probe_interfaces false
+.RE
+.fi
+.RS 10n
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.10 and higher.
+.RE
+.SS "Debug flags"
+\fBsudo\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that can help track down what
+\fBsudo\fR
+is doing internally if there is a problem.
+.PP
+A
+\fRDebug\fR
+line consists of the
+\fRDebug\fR
+keyword, followed by the name of the program (or plugin) to debug
+(\fBsudo\fR, \fBvisudo\fR, \fBsudoreplay\fR, \fBsudoers\fR),
+the debug file name and a comma-separated list of debug flags.
+The debug flag syntax used by
+\fBsudo\fR
+and the
+\fBsudoers\fR
+plugin is
+\fIsubsystem\fR@\fIpriority\fR
+but a plugin is free to use a different format so long as it does
+not include a comma
+(\(oq\&,\(cq).
+.PP
+For example:
+.nf
+.sp
+.RS 6n
+Debug sudo /var/log/sudo_debug all@warn,plugin@info
+.RE
+.fi
+.PP
+would log all debugging statements at the
+\fIwarn\fR
+level and higher in addition to those at the
+\fIinfo\fR
+level for the plugin subsystem.
+.PP
+As of
+\fBsudo\fR
+1.8.12, multiple
+\fRDebug\fR
+entries may be specified per program.
+Older versions of
+\fBsudo\fR
+only support a single
+\fRDebug\fR
+entry per program.
+Plugin-specific
+\fRDebug\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)
+or by the plugin's fully-qualified path name.
+Previously, the
+\fBsudoers\fR
+plugin shared the same
+\fRDebug\fR
+entry as the
+\fBsudo\fR
+front end and could not be configured separately.
+.PP
+The following priorities are supported, in order of decreasing severity:
+\fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, \fIinfo\fR, \fItrace\fR
+and
+\fIdebug\fR.
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+\fInotice\fR
+would include debug messages logged at
+\fInotice\fR
+and higher.
+.PP
+The priorities
+\fItrace\fR
+and
+\fIdebug\fR
+also include function call tracing which logs when a function is
+entered and when it returns.
+For example, the following trace is for the
+\fBget_user_groups\fR()
+function located in src/sudo.c:
+.nf
+.sp
+.RS 6n
+sudo[123] -> get_user_groups @ src/sudo.c:385
+sudo[123] <- get_user_groups @ src/sudo.c:429 := groups=10,0,5
+.RE
+.fi
+.PP
+When the function is entered, indicated by a right arrow
+\(oq->\(cq,
+the program, process ID, function, source file and line number
+are logged.
+When the function returns, indicated by a left arrow
+\(oq<-\(cq,
+the same information is logged along with the return value.
+In this case, the return value is a string.
+.PP
+The following subsystems are used by the
+\fBsudo\fR
+front-end:
+.TP 12n
+\fIall\fR
+matches every subsystem
+.TP 12n
+\fIargs\fR
+command line argument processing
+.TP 12n
+\fIconv\fR
+user conversation
+.TP 12n
+\fIedit\fR
+sudoedit
+.TP 12n
+\fIevent\fR
+event subsystem
+.TP 12n
+\fIexec\fR
+command execution
+.TP 12n
+\fImain\fR
+\fBsudo\fR
+main function
+.TP 12n
+\fInetif\fR
+network interface handling
+.TP 12n
+\fIpcomm\fR
+communication with the plugin
+.TP 12n
+\fIplugin\fR
+plugin configuration
+.TP 12n
+\fIpty\fR
+pseudo-terminal related code
+.TP 12n
+\fIselinux\fR
+SELinux-specific handling
+.TP 12n
+\fIutil\fR
+utility functions
+.TP 12n
+\fIutmp\fR
+utmp handling
+.PP
+The
+sudoers(@mansectform@)
+plugin includes support for additional subsystems.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+\fBsudo\fR
+front end configuration
+.SH "EXAMPLES"
+.nf
+.RS 0n
+#
+# Default @sysconfdir@/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to @plugindir@ unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy sudoers.so
+#Plugin sudoers_io sudoers.so
+#Plugin sudoers_audit sudoers.so
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec @plugindir@/sudo_noexec.so
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir @plugindir@
+
+#
+# Sudo developer mode:
+# Set developer_mode true|false
+#
+# Allow loading of plugins that are owned by non-root or are writable
+# by "group" or "other". Should only be used during plugin development.
+#Set developer_mode true
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo /var/log/sudo_debug all@debug
+#Debug sudoers.so /var/log/sudoers_debug all@debug
+.RE
+.fi
+.SH "SEE ALSO"
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "HISTORY"
+See the HISTORY file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo.conf.man.in.sed b/doc/sudo.conf.man.in.sed
new file mode 100644
index 0000000..2534bc8
--- /dev/null
+++ b/doc/sudo.conf.man.in.sed
@@ -0,0 +1,15 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+\1/
+
+/^\.TP 10n$/ {
+ N
+ /^.TP 10n\nsesh$/ {
+ i\
+.if \\n(SL \\{\\
+ }
+}
+
+/^\\fI@sesh_file@\\fR\.$/ {
+ a\
+.\\}
+}
diff --git a/doc/sudo.conf.mdoc.in b/doc/sudo.conf.mdoc.in
new file mode 100644
index 0000000..2d572e5
--- /dev/null
+++ b/doc/sudo.conf.mdoc.in
@@ -0,0 +1,796 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2010-2020 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.
+.\"
+.nr SL @SEMAN@
+.Dd December 5, 2020
+.Dt SUDO.CONF @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo.conf
+.Nd configuration for sudo front end
+.Sh DESCRIPTION
+The
+.Nm sudo.conf
+file is used to configure the
+.Nm sudo
+front end.
+It specifies the security policy and I/O logging plugins, debug flags
+as well as plugin-agnostic path names and settings.
+.Pp
+The
+.Nm
+file supports the following directives, described in detail below.
+.Bl -tag -width 8n
+.It Plugin
+a security policy or I/O logging plugin
+.It Path
+a plugin-agnostic path
+.It Set
+a front end setting, such as
+.Em disable_coredump
+or
+.Em group_source
+.It Debug
+debug flags to aid in debugging
+.Nm sudo ,
+.Nm sudoreplay ,
+.Nm visudo ,
+and the
+.Nm sudoers
+plugin.
+.El
+.Pp
+The pound sign
+.Pq Ql #
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+Note that leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.Pp
+Non-comment lines that don't begin with
+.Li Plugin ,
+.Li Path ,
+.Li Debug ,
+or
+.Li Set
+are silently ignored.
+.Pp
+The
+.Nm
+file is always parsed in the
+.Dq Li C
+locale.
+.Ss Plugin configuration
+.Nm sudo
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+.Nm sudo
+front end.
+Plugins are dynamically loaded based on the contents of
+.Nm .
+.Pp
+A
+.Li Plugin
+line consists of the
+.Li Plugin
+keyword, followed by the
+.Em symbol_name
+and the
+.Em path
+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 ,
+or
+.Li policy_plugin
+struct contained in the plugin.
+If a plugin implements multiple plugin types, there must be a
+.Li Plugin
+line for each unique symbol name.
+The
+.Em path
+may be fully qualified or relative.
+If not fully qualified, it is relative to the directory
+specified by the
+.Em plugin_dir
+.Li Path
+setting, which defaults to
+.Pa @plugindir@ .
+In other words:
+.Bd -literal -offset indent
+Plugin sudoers_policy sudoers.so
+.Ed
+.Pp
+is equivalent to:
+.Bd -literal -offset indent
+Plugin sudoers_policy @plugindir@/sudoers.so
+.Ed
+.Pp
+If the plugin was compiled statically into the
+.Nm sudo
+binary instead of being installed as a dynamic shared object, the
+.Em path
+should be specified without a leading directory,
+as it does not actually exist in the file system.
+For example:
+.Bd -literal -offset indent
+Plugin sudoers_policy sudoers.so
+.Ed
+.Pp
+Starting with
+.Nm sudo
+1.8.5, any additional parameters after the
+.Em path
+are passed as arguments to the plugin's
+.Em open
+function.
+For example, to override the compile-time default sudoers file mode:
+.Bd -literal -offset indent
+Plugin sudoers_policy sudoers.so sudoers_mode=0440
+.Ed
+.Pp
+See the
+.Xr sudoers @mansectform@
+manual for a list of supported arguments.
+.Pp
+The same dynamic shared object may contain multiple plugins,
+each with a different symbol name.
+The file must be owned by uid 0 and only writable by its owner.
+Because of ambiguities that arise from composite policies, only a single
+policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+.Pp
+If no
+.Nm
+file is present, or if it contains no
+.Li Plugin
+lines, the
+.Nm sudoers
+plugin will be used as the default security policy, for I/O logging
+(if enabled by the policy) and for auditing.
+This is equivalent to the following:
+.Bd -literal -offset indent
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+Plugin sudoers_audit sudoers.so
+.Ed
+.Pp
+Starting with
+.Nm sudo
+version 1.9.1, some of the logging functionality of the
+.Nm sudoers
+plugin has been moved from the policy plugin to an audit plugin.
+To maintain compatibility with
+.Nm
+files from older
+.Nm sudo
+versions, if
+.Nm sudoers
+is configured as the security policy, it will be used as an audit
+plugin as well.
+This guarantees that the logging behavior will be consistnet with that of
+.Nm sudo
+versions 1.9.0 and below.
+.Pp
+For more information on the
+.Nm sudo
+plugin architecture, see the
+.Xr sudo_plugin @mansectform@
+manual.
+.Ss Path settings
+A
+.Li Path
+line consists of the
+.Li Path
+keyword, followed by the name of the path to set and its value.
+For example:
+.Bd -literal -offset indent
+Path noexec @noexec_file@
+Path askpass /usr/X11R6/bin/ssh-askpass
+.Ed
+.Pp
+If no path name is specified, features relying on the specified
+setting will be disabled.
+Disabling
+.Li Path
+settings is only supported in
+.Nm sudo
+version 1.8.16 and higher.
+.Pp
+The following plugin-agnostic paths may be set in the
+.Pa @sysconfdir@/sudo.conf
+file:
+.Bl -tag -width 8n
+.It askpass
+The fully qualified path to a helper program used to read the user's
+password when no terminal is available.
+This may be the case when
+.Nm sudo
+is executed from a graphical (as opposed to text-based) application.
+The program specified by
+.Em askpass
+should display the argument passed to it as the prompt and write
+the user's password to the standard output.
+The value of
+.Em askpass
+may be overridden by the
+.Ev SUDO_ASKPASS
+environment variable.
+.It devsearch
+An ordered, colon-separated search path of directories to look in for
+device nodes.
+This is used when mapping the process's tty device number to a device name
+on systems that do not provide such a mechanism.
+Sudo will
+.Em not
+recurse into sub-directories.
+If terminal devices may be located in a sub-directory of
+.Pa /dev ,
+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
+.Pp
+This option is ignored on systems that support either the
+.Fn devname
+or
+.Fn _ttyname_dev
+functions, for example
+.Bx ,
+macOS and Solaris.
+.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 execvP ,
+.Fn execvp ,
+.Fn execvpe ,
+.Fn fexecve ,
+.Fn popen ,
+.Fn posix_spawn ,
+.Fn posix_spawnp ,
+.Fn system ,
+and
+.Fn wordexp
+library functions that prevent the execution of further commands.
+This is used to implement the
+.Em noexec
+functionality on systems that support
+.Ev LD_PRELOAD
+or its equivalent.
+The default value is
+.Pa @noexec_file@ .
+.It plugin_dir
+The default directory to use when searching for plugins
+that are specified without a fully qualified path name.
+The default value is
+.Pa @plugindir@ .
+.if \n(SL \{\
+.It sesh
+The fully-qualified path to the
+.Nm sesh
+binary.
+This setting is only used when
+.Nm sudo
+is built with SELinux support.
+The default value is
+.Pa @sesh_file@ .
+.\}
+.El
+.Ss Other settings
+The
+.Nm
+file also supports the following front end settings:
+.Bl -tag -width 8n
+.It disable_coredump
+Core dumps of
+.Nm sudo
+itself are disabled by default to prevent the disclosure of potentially
+sensitive information.
+To aid in debugging
+.Nm sudo
+crashes, you may wish to re-enable core dumps by setting
+.Dq disable_coredump
+to false in
+.Nm
+as follows:
+.Bd -literal -offset indent
+Set disable_coredump false
+.Ed
+.Pp
+All modern operating systems place restrictions on core dumps
+from set-user-ID processes like
+.Nm sudo
+so this option can be enabled without compromising security.
+To actually get a
+.Nm sudo
+core file you will likely need to enable core dumps for set-user-ID processes.
+On
+.Bx
+and Linux systems this is accomplished in the
+.Xr sysctl 8
+command.
+On Solaris, the
+.Xr coreadm 1m
+command is used to configure core dump behavior.
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.4 and higher.
+.It developer_mode
+By default
+.Nm sudo
+refuses to load plugins which can be modified by other than the root user.
+The plugin should be owned by root and write access permissions should be
+disabled for
+.Dq group
+and
+.Sm off
+.Dq other
+\&.
+.Sm on
+To make development of a plugin easier, you can disable that by setting
+.Dq developer_mode
+option to true in
+.Nm sudo.conf
+as follows:
+.Bd -literal -offset indent
+Set developer_mode true
+.Ed
+.Pp
+Please note that this creates a security risk, so it is not recommended
+on critical systems such as a desktop machine for daily use, but is intended
+to be used in development environments (VM, container, etc).
+Before enabling developer mode, ensure you understand the implications.
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.9.0 and higher.
+.It group_source
+.Nm sudo
+passes the invoking user's group list to the policy and I/O plugins.
+On most systems, there is an upper limit to the number of groups that
+a user may belong to simultaneously (typically 16 for compatibility
+with NFS).
+On systems with the
+.Xr getconf 1
+utility, running:
+.Dl getconf NGROUPS_MAX
+will return the maximum number of groups.
+.Pp
+However, it is still possible to be a member of a larger number of
+groups--they simply won't be included in the group list returned
+by the kernel for the user.
+Starting with
+.Nm sudo
+version 1.8.7, if the user's kernel group list has the maximum number
+of entries,
+.Nm sudo
+will consult the group database directly to determine the group list.
+This makes it possible for the security policy to perform matching by group
+name even when the user is a member of more than the maximum number of groups.
+.Pp
+The
+.Em group_source
+setting allows the administrator to change this default behavior.
+Supported values for
+.Em group_source
+are:
+.Bl -tag -width 8n
+.It static
+Use the static group list that the kernel returns.
+Retrieving the group list this way is very fast but it is subject
+to an upper limit as described above.
+It is
+.Dq static
+in that it does not reflect changes to the group database made
+after the user logs in.
+This was the default behavior prior to
+.Nm sudo
+1.8.7.
+.It dynamic
+Always query the group database directly.
+It is
+.Dq dynamic
+in that changes made to the group database after the user logs in
+will be reflected in the group list.
+On some systems, querying the group database for all of a user's
+groups can be time consuming when querying a network-based group
+database.
+Most operating systems provide an efficient method of performing
+such queries.
+Currently,
+.Nm sudo
+supports efficient group queries on AIX,
+.Bx ,
+HP-UX, Linux and Solaris.
+.It adaptive
+Only query the group database if the static group list returned
+by the kernel has the maximum number of entries.
+This is the default behavior in
+.Nm sudo
+1.8.7 and higher.
+.El
+.Pp
+For example, to cause
+.Nm sudo
+to only use the kernel's static list of groups for the user:
+.Bd -literal -offset indent
+Set group_source static
+.Ed
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.7 and higher.
+.It max_groups
+The maximum number of user groups to retrieve from the group database.
+Values less than one will be ignored.
+This setting is only used when querying the group database directly.
+It is intended to be used on systems where it is not possible to detect
+when the array to be populated with group entries is not sufficiently large.
+By default,
+.Nm sudo
+will allocate four times the system's maximum number of groups (see above)
+and retry with double that number if the group database query fails.
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.7 and higher.
+It should not be required in
+.Nm sudo
+versions 1.8.24 and higher and may be removed in a later release.
+.It probe_interfaces
+By default,
+.Nm sudo
+will probe the system's network interfaces and pass the IP address
+of each enabled interface to the policy plugin.
+This makes it possible for the plugin to match rules based on the IP address
+without having to query DNS.
+On Linux systems with a large number of virtual interfaces, this may
+take a non-negligible amount of time.
+If IP-based matching is not required, network interface probing
+can be disabled as follows:
+.Bd -literal -offset indent
+Set probe_interfaces false
+.Ed
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.10 and higher.
+.El
+.Ss Debug flags
+.Nm sudo
+versions 1.8.4 and higher support a flexible debugging framework
+that can help track down what
+.Nm sudo
+is doing internally if there is a problem.
+.Pp
+A
+.Li Debug
+line consists of the
+.Li Debug
+keyword, followed by the name of the program (or plugin) to debug
+.Pq Nm sudo , Nm visudo , Nm sudoreplay , Nm sudoers ,
+the debug file name and a comma-separated list of debug flags.
+The debug flag syntax used by
+.Nm sudo
+and the
+.Nm sudoers
+plugin is
+.Em subsystem Ns @ Ns Em priority
+but a plugin is free to use a different format so long as it does
+not include a comma
+.Pq Ql \&, .
+.Pp
+For example:
+.Bd -literal -offset indent
+Debug sudo /var/log/sudo_debug all@warn,plugin@info
+.Ed
+.Pp
+would log all debugging statements at the
+.Em warn
+level and higher in addition to those at the
+.Em info
+level for the plugin subsystem.
+.Pp
+As of
+.Nm sudo
+1.8.12, multiple
+.Li Debug
+entries may be specified per program.
+Older versions of
+.Nm sudo
+only support a single
+.Li Debug
+entry per program.
+Plugin-specific
+.Li 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 )
+or by the plugin's fully-qualified path name.
+Previously, the
+.Nm sudoers
+plugin shared the same
+.Li Debug
+entry as the
+.Nm sudo
+front end and could not be configured separately.
+.Pp
+The following priorities are supported, in order of decreasing severity:
+.Em crit , err , warn , notice , diag , info , trace
+and
+.Em debug .
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+.Em notice
+would include debug messages logged at
+.Em notice
+and higher.
+.Pp
+The priorities
+.Em trace
+and
+.Em debug
+also include function call tracing which logs when a function is
+entered and when it returns.
+For example, the following trace is for the
+.Fn get_user_groups
+function located in src/sudo.c:
+.Bd -literal -offset indent
+sudo[123] -> get_user_groups @ src/sudo.c:385
+sudo[123] <- get_user_groups @ src/sudo.c:429 := groups=10,0,5
+.Ed
+.Pp
+When the function is entered, indicated by a right arrow
+.Ql -> ,
+the program, process ID, function, source file and line number
+are logged.
+When the function returns, indicated by a left arrow
+.Ql <- ,
+the same information is logged along with the return value.
+In this case, the return value is a string.
+.Pp
+The following subsystems are used by the
+.Nm sudo
+front-end:
+.Bl -tag -width Fl
+.It Em all
+matches every subsystem
+.It Em args
+command line argument processing
+.It Em conv
+user conversation
+.It Em edit
+sudoedit
+.It Em event
+event subsystem
+.It Em exec
+command execution
+.It Em main
+.Nm sudo
+main function
+.It Em netif
+network interface handling
+.It Em pcomm
+communication with the plugin
+.It Em plugin
+plugin configuration
+.It Em pty
+pseudo-terminal related code
+.It Em selinux
+SELinux-specific handling
+.It Em util
+utility functions
+.It Em utmp
+utmp handling
+.El
+.Pp
+The
+.Xr sudoers @mansectform@
+plugin includes support for additional subsystems.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+.Nm sudo
+front end configuration
+.El
+.Sh EXAMPLES
+.Bd -literal
+#
+# Default @sysconfdir@/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to @plugindir@ unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy sudoers.so
+#Plugin sudoers_io sudoers.so
+#Plugin sudoers_audit sudoers.so
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec @plugindir@/sudo_noexec.so
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir @plugindir@
+
+#
+# Sudo developer mode:
+# Set developer_mode true|false
+#
+# Allow loading of plugins that are owned by non-root or are writable
+# by "group" or "other". Should only be used during plugin development.
+#Set developer_mode true
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo /var/log/sudo_debug all@debug
+#Debug sudoers.so /var/log/sudoers_debug all@debug
+.Ed
+.Sh SEE ALSO
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh HISTORY
+See the HISTORY file in the
+.Nm sudo
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo.man.in b/doc/sudo.man.in
new file mode 100644
index 0000000..46dcc67
--- /dev/null
+++ b/doc/sudo.man.in
@@ -0,0 +1,1495 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2020
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.TH "SUDO" "@mansectsu@" "September 1, 2020" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo\fR,
+\fBsudoedit\fR
+\- execute a command as another user
+.SH "SYNOPSIS"
+.HP 5n
+\fBsudo\fR
+\fB\-h\fR\ |\ \fB\-K\fR\ |\ \fB\-k\fR\ |\ \fB\-V\fR
+.br
+.PD 0
+.HP 5n
+\fBsudo\fR
+\fB\-v\fR
+[\fB\-ABknS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-u\fR\ \fIuser\fR]
+.br
+.HP 5n
+\fBsudo\fR
+\fB\-l\fR
+[\fB\-ABknS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-U\fR\ \fIuser\fR]
+[\fB\-u\fR\ \fIuser\fR]
+[\fIcommand\fR]
+.br
+.HP 5n
+\fBsudo\fR
+[\fB\-ABbEHnPS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-C\fR\ \fInum\fR]
+.if \n(LC [\fB\-c\fR\ \fIclass\fR]
+[\fB\-D\fR\ \fIdirectory\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-R\fR\ \fIdirectory\fR]
+.if \n(SL [\fB\-r\fR\ \fIrole\fR]
+.if \n(SL [\fB\-t\fR\ \fItype\fR]
+[\fB\-T\fR\ \fItimeout\fR]
+[\fB\-u\fR\ \fIuser\fR]
+[\fIVAR\fR=\fIvalue\fR]
+[\fB\-i\fR\ |\ \fB\-s\fR]
+[\fIcommand\fR]
+.br
+.HP 9n
+\fBsudoedit\fR
+[\fB\-ABknS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-C\fR\ \fInum\fR]
+.if \n(LC [\fB\-c\fR\ \fIclass\fR]
+[\fB\-D\fR\ \fIdirectory\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-R\fR\ \fIdirectory\fR]
+.if \n(SL [\fB\-r\fR\ \fIrole\fR]
+.if \n(SL [\fB\-t\fR\ \fItype\fR]
+[\fB\-T\fR\ \fItimeout\fR]
+[\fB\-u\fR\ \fIuser\fR]
+\fIfile\ ...\fR
+.PD
+.SH "DESCRIPTION"
+\fBsudo\fR
+allows a permitted user to execute a
+\fIcommand\fR
+as the superuser or another user, as specified by the security
+policy.
+The invoking user's real
+(\fInot\fR effective)
+user-ID is used to determine the user name with which
+to query the security policy.
+.PP
+\fBsudo\fR
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+\fBsudo\fR
+front end.
+The default security policy is
+\fIsudoers\fR,
+which is configured via the file
+\fI@sysconfdir@/sudoers\fR,
+or via LDAP.
+See the
+\fIPlugins\fR
+section for more information.
+.PP
+The security policy determines what privileges, if any, a user has
+to run
+\fBsudo\fR.
+The policy may require that users authenticate themselves with a
+password or another authentication mechanism.
+If authentication is required,
+\fBsudo\fR
+will exit if the user's password is not entered within a configurable
+time limit.
+This limit is policy-specific; the default password prompt timeout
+for the
+\fIsudoers\fR
+security policy is
+\fR@password_timeout@\fR
+minutes.
+.PP
+Security policies may support credential caching to allow the user
+to run
+\fBsudo\fR
+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.
+See the
+\fItimestamp_type\fR
+and
+\fItimestamp_timeout\fR
+options in
+sudoers(@mansectform@)
+for more information.
+By running
+\fBsudo\fR
+with the
+\fB\-v\fR
+option, a user can update the cached credentials without running a
+\fIcommand\fR.
+.PP
+On systems where
+\fBsudo\fR
+is the primary method of gaining superuser privileges, it is imperative
+to avoid syntax errors in the security policy configuration files.
+For the default security policy,
+sudoers(@mansectform@),
+changes to the configuration files should be made using the
+visudo(@mansectsu@)
+utility which will ensure that no syntax errors are introduced.
+.PP
+When invoked as
+\fBsudoedit\fR,
+the
+\fB\-e\fR
+option (described below), is implied.
+.PP
+Security policies may log successful and failed attempts to use
+\fBsudo\fR.
+If an I/O plugin is configured, the running command's input and
+output may be logged as well.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-A\fR, \fB\--askpass\fR
+Normally, if
+\fBsudo\fR
+requires a password, it will read it from the user's terminal.
+If the
+\fB\-A\fR (\fIaskpass\fR)
+option is specified, a (possibly graphical) helper program is
+executed to read the user's password and output the password to the
+standard output.
+If the
+\fRSUDO_ASKPASS\fR
+environment variable is set, it specifies the path to the helper
+program.
+Otherwise, if
+sudo.conf(@mansectform@)
+contains a line specifying the askpass program, that value will be
+used.
+For example:
+.nf
+.sp
+.RS 16n
+# Path to askpass helper program
+Path askpass /usr/X11R6/bin/ssh-askpass
+.RE
+.fi
+.RS 12n
+.sp
+If no askpass program is available,
+\fBsudo\fR
+will exit with an error.
+.RE
+.if \n(BA \{\
+.TP 12n
+\fB\-a\fR \fItype\fR, \fB\--auth-type\fR=\fItype\fR
+Use the specified
+BSD
+authentication
+\fItype\fR
+when validating the user, if allowed by
+\fI/etc/login.conf\fR.
+The system administrator may specify a list of sudo-specific
+authentication methods by adding an
+\(lqauth-sudo\(rq
+entry in
+\fI/etc/login.conf\fR.
+This option is only available on systems that support
+BSD
+authentication.
+.\}
+.TP 12n
+\fB\-B\fR, \fB\--bell\fR
+Ring the bell as part of the password promp when a terminal is present.
+This option has no effect if an askpass program is used.
+.TP 12n
+\fB\-b\fR, \fB\--background\fR
+Run the given command in the background.
+Note that it is not possible to use shell job control to manipulate
+background processes started by
+\fBsudo\fR.
+Most interactive commands will fail to work properly in background
+mode.
+.TP 12n
+\fB\-C\fR \fInum\fR, \fB\--close-from\fR=\fInum\fR
+Close all file descriptors greater than or equal to
+\fInum\fR
+before executing a command.
+Values less than three are not permitted.
+By default,
+\fBsudo\fR
+will close all open file descriptors other than standard input,
+standard output and standard error when executing a command.
+The security policy may restrict the user's ability to use this option.
+The
+\fIsudoers\fR
+policy only permits use of the
+\fB\-C\fR
+option when the administrator has enabled the
+\fIclosefrom_override\fR
+option.
+.if \n(LC \{\
+.TP 12n
+\fB\-c\fR \fIclass\fR, \fB\--login-class\fR=\fIclass\fR
+Run the command with resource limits and scheduling priority of
+the specified login
+\fIclass\fR.
+The
+\fIclass\fR
+argument can be either a class name as defined in
+\fI/etc/login.conf\fR,
+or a single
+\(oq\-\(cq
+character.
+If
+\fIclass\fR
+is
+\fB-\fR,
+the default login class of the target user will be used.
+Otherwise, the command must be run as the superuser (user-ID 0), or
+\fBsudo\fR
+must be run from a shell that is already running as the superuser.
+If the command is being run as a login shell, additional
+\fI/etc/login.conf\fR
+settings, such as the umask and environment variables, will
+be applied, if present.
+This option is only available on systems with
+BSD
+login classes.
+.\}
+.TP 12n
+\fB\-D\fR \fIdirectory\fR, \fB\--chdir\fR=\fIdirectory\fR
+Run the command in the specified
+\fIdirectory\fR
+instead of the current working directory.
+The security policy may return an error if the user does not have
+permission to specify the working directory.
+.TP 12n
+\fB\-E\fR, \fB\--preserve-env\fR
+Indicates to the security policy that the user wishes to
+preserve their existing environment variables.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+.TP 12n
+\fB\--preserve-env=list\fR
+Indicates to the security policy that the user wishes to add the
+comma-separated list of environment variables to those preserved
+from the user's environment.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+This option may be specified multiple times.
+.TP 12n
+\fB\-e\fR, \fB\--edit\fR
+Edit one or more files instead of running a command.
+In lieu of a path name, the string "sudoedit" is used when consulting
+the security policy.
+If the user is authorized by the policy, the following steps are
+taken:
+.RS 16n
+.TP 5n
+1.\&
+Temporary copies are made of the files to be edited with the owner
+set to the invoking user.
+.TP 5n
+2.\&
+The editor specified by the policy is run to edit the temporary
+files.
+The
+\fIsudoers\fR
+policy uses the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+and
+\fREDITOR\fR
+environment variables (in that order).
+If none of
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+are set, the first program listed in the
+\fIeditor\fR
+sudoers(@mansectform@)
+option is used.
+.TP 5n
+3.\&
+If they have been modified, the temporary files are copied back to
+their original location and the temporary versions are removed.
+.RE
+.RS 12n
+.sp
+To help prevent the editing of unauthorized files, the following
+restrictions are enforced unless explicitly allowed by the security policy:
+.RS 16n
+.TP 3n
+\fB\(bu\fR
+Symbolic links may not be edited (version 1.8.15 and higher).
+.TP 3n
+\fB\(bu\fR
+Symbolic links along the path to be edited are not followed when the
+parent directory is writable by the invoking user unless that user
+is root (version 1.8.16 and higher).
+.TP 3n
+\fB\(bu\fR
+Files located in a directory that is writable by the invoking user may
+not be edited unless that user is root (version 1.8.16 and higher).
+.RE
+.sp
+Users are never allowed to edit device special files.
+.sp
+If the specified file does not exist, it will be created.
+Note that unlike most commands run by
+\fIsudo\fR,
+the editor is run with the invoking user's environment unmodified.
+If the temporary file becomes empty after editing, the user will
+be prompted before it is installed.
+If, for some reason,
+\fBsudo\fR
+is unable to update a file with its edited version, the user will
+receive a warning and the edited copy will remain in a temporary
+file.
+.RE
+.TP 12n
+\fB\-g\fR \fIgroup\fR, \fB\--group\fR=\fIgroup\fR
+Run the command with the primary group set to
+\fIgroup\fR
+instead of the primary group specified by the target
+user's password database entry.
+The
+\fIgroup\fR
+may be either a group name or a numeric group-ID
+(GID)
+prefixed with the
+\(oq#\(cq
+character (e.g.,
+\fR#0\fR
+for GID 0).
+When running a command as a GID, many shells require that the
+\(oq#\(cq
+be escaped with a backslash
+(\(oq\e\(cq).
+If no
+\fB\-u\fR
+option is specified, the command will be run as the invoking user.
+In either case, the primary group will be set to
+\fIgroup\fR.
+The
+\fIsudoers\fR
+policy permits any of the target user's groups to be specified via
+the
+\fB\-g\fR
+option as long as the
+\fB\-P\fR
+option is not in use.
+.TP 12n
+\fB\-H\fR, \fB\--set-home\fR
+Request that the security policy set the
+\fRHOME\fR
+environment variable to the home directory specified by the target
+user's password database entry.
+Depending on the policy, this may be the default behavior.
+.TP 12n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-h\fR \fIhost\fR, \fB\--host\fR=\fIhost\fR
+Run the command on the specified
+\fIhost\fR
+if the security policy plugin supports remote commands.
+Note that the
+\fIsudoers\fR
+plugin does not currently support running remote commands.
+This may also be used in conjunction with the
+\fB\-l\fR
+option to list a user's privileges for the remote host.
+.TP 12n
+\fB\-i\fR, \fB\--login\fR
+Run the shell specified by the target user's password database entry
+as a login shell.
+This means that login-specific resource files such as
+\fI.profile\fR,
+\fI.bash_profile\fR
+or
+\fI.login\fR
+will be read by the shell.
+If a command is specified, it is passed to the shell for execution
+via the shell's
+\fB\-c\fR
+option.
+If no command is specified, an interactive shell is executed.
+\fBsudo\fR
+attempts to change to that user's home directory before running the
+shell.
+The command is run with an environment similar to the one
+a user would receive at log in.
+Note that most shells behave differently when a command is specified
+as compared to an interactive session; consult the shell's manual
+for details.
+The
+\fICommand environment\fR
+section in the
+sudoers(@mansectform@)
+manual documents how the
+\fB\-i\fR
+option affects the environment in which a command is run when the
+\fIsudoers\fR
+policy is in use.
+.TP 12n
+\fB\-K\fR, \fB\--remove-timestamp\fR
+Similar to the
+\fB\-k\fR
+option, except that it removes the user's cached credentials entirely
+and may not be used in conjunction with a command or other option.
+This option does not require a password.
+Not all security policies support credential caching.
+.TP 12n
+\fB\-k\fR, \fB\--reset-timestamp\fR
+When used without a command, invalidates the user's cached credentials.
+In other words, the next time
+\fBsudo\fR
+is run a password will be required.
+This option does not require a password and was added to allow a
+user to revoke
+\fBsudo\fR
+permissions from a
+\fI.logout\fR
+file.
+.sp
+When used in conjunction with a command or an option that may require
+a password, this option will cause
+\fBsudo\fR
+to ignore the user's cached credentials.
+As a result,
+\fBsudo\fR
+will prompt for a password (if one is required by the security
+policy) and will not update the user's cached credentials.
+.sp
+Not all security policies support credential caching.
+.TP 12n
+\fB\-l\fR, \fB\--list\fR
+If no
+\fIcommand\fR
+is specified,
+list the allowed (and forbidden) commands for the
+invoking user (or the user specified by the
+\fB\-U\fR
+option) on the current host.
+A longer list format is used if this option is specified multiple times
+and the security policy supports a verbose output format.
+.sp
+If a
+\fIcommand\fR
+is specified and is permitted by the security policy, the fully-qualified
+path to the command is displayed along with any command line
+arguments.
+If a
+\fIcommand\fR
+is specified but not allowed by the policy,
+\fBsudo\fR
+will exit with a status value of 1.
+.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,
+\fBsudo\fR
+will display an error message and exit.
+.TP 12n
+\fB\-P\fR, \fB\--preserve-groups\fR
+Preserve the invoking user's group vector unaltered.
+By default, the
+\fIsudoers\fR
+policy will initialize the group vector to the list of groups the
+target user is a member of.
+The real and effective group-IDs, however, are still set to match
+the target user.
+.TP 12n
+\fB\-p\fR \fIprompt\fR, \fB\--prompt\fR=\fIprompt\fR
+Use a custom password prompt with optional escape sequences.
+The following percent
+(\(oq%\(cq)
+escape sequences are supported by the
+\fIsudoers\fR
+policy:
+.PP
+.RS 12n
+.PD 0
+.TP 4n
+\fR%H\fR
+expanded to the host name including the domain name (on if the
+machine's host name is fully qualified or the
+\fIfqdn\fR
+option is set in
+sudoers(@mansectform@))
+.PD
+.TP 4n
+\fR%h\fR
+expanded to the local host name without the domain name
+.TP 4n
+\fR%p\fR
+expanded to the name of the user whose password is being requested
+(respects the
+\fIrootpw\fR,
+\fItargetpw\fR,
+and
+\fIrunaspw\fR
+flags in
+sudoers(@mansectform@))
+.TP 4n
+\fR\&%U\fR
+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
+expanded to the invoking user's login name
+.TP 4n
+\fR%%\fR
+two consecutive
+\(oq%\(cq
+characters are collapsed into a single
+\(oq%\(cq
+character
+.PP
+The custom prompt will override the default prompt specified by either
+the security policy or the
+\fRSUDO_PROMPT\fR
+environment variable.
+On systems that use PAM, the custom prompt will also override the prompt
+specified by a PAM module unless the
+\fIpassprompt_override\fR
+flag is disabled in
+\fIsudoers\fR.
+.RE
+.TP 12n
+\fB\-R\fR \fIdirectory\fR, \fB\--chroot\fR=\fIdirectory\fR
+Change to the specified root
+\fIdirectory\fR
+(see
+chroot(@mansectsu@))
+before running the command.
+The security policy may return an error if the user does not have
+permission to specify the root directory.
+.if \n(SL \{\
+.TP 12n
+\fB\-r\fR \fIrole\fR, \fB\--role\fR=\fIrole\fR
+Run the command with an SELinux security context that includes
+the specified
+\fIrole\fR.
+.\}
+.TP 12n
+\fB\-S\fR, \fB\--stdin\fR
+Write the prompt to the standard error and read the password from the
+standard input instead of using the terminal device.
+.TP 12n
+\fB\-s\fR, \fB\--shell\fR
+Run the shell specified by the
+\fRSHELL\fR
+environment variable if it is set or the shell specified by the
+invoking user's password database entry.
+If a command is specified, it is passed to the shell for execution
+via the shell's
+\fB\-c\fR
+option.
+If no command is specified, an interactive shell is executed.
+Note that most shells behave differently when a command is specified
+as compared to an interactive session; consult the shell's manual
+for details.
+.if \n(SL \{\
+.TP 12n
+\fB\-t\fR \fItype\fR, \fB\--type\fR=\fItype\fR
+Run the command with an SELinux security context that includes
+the specified
+\fItype\fR.
+If no
+\fItype\fR
+is specified, the default type is derived from the role.
+.\}
+.TP 12n
+\fB\-U\fR \fIuser\fR, \fB\--other-user\fR=\fIuser\fR
+Used in conjunction with the
+\fB\-l\fR
+option to list the privileges for
+\fIuser\fR
+instead of for the invoking user.
+The security policy may restrict listing other users' privileges.
+The
+\fIsudoers\fR
+policy only allows root or a user with the
+\fRALL\fR
+privilege on the current host to use this option.
+.TP 12n
+\fB\-T\fR \fItimeout\fR, \fB\--command-timeout\fR=\fItimeout\fR
+Used to set a timeout for the command.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The security policy may restrict the ability to set command timeouts.
+The
+\fIsudoers\fR
+policy requires that user-specified timeouts be explicitly enabled.
+.TP 12n
+\fB\-u\fR \fIuser\fR, \fB\--user\fR=\fIuser\fR
+Run the command as a user other than the default target user
+(usually
+\fIroot\fR).
+The
+\fIuser\fR
+may be either a user name or a numeric user-ID
+(UID)
+prefixed with the
+\(oq#\(cq
+character (e.g.,
+\fR#0\fR
+for UID 0).
+When running commands as a UID, many shells require that the
+\(oq#\(cq
+be escaped with a backslash
+(\(oq\e\(cq).
+Some security policies may restrict UIDs
+to those listed in the password database.
+The
+\fIsudoers\fR
+policy allows UIDs that are not in the password database as long as the
+\fItargetpw\fR
+option is not set.
+Other security policies may not support this.
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo\fR
+version string as well as the version string of the security
+policy plugin and any I/O plugins.
+If the invoking user is already root the
+\fB\-V\fR
+option will display the arguments passed to configure when
+\fBsudo\fR
+was built and plugins may display more verbose information such as
+default options.
+.TP 12n
+\fB\-v\fR, \fB\--validate\fR
+Update the user's cached credentials, authenticating the user
+if necessary.
+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.
+Not all security policies support cached credentials.
+.TP 12n
+\fB\--\fR
+The
+\fB\--\fR
+option indicates that
+\fBsudo\fR
+should stop processing command line arguments.
+.PP
+Options that take a value may only be specified once unless
+otherwise indicated in the description.
+This is to help guard against problems caused by poorly written
+scripts that invoke
+\fBsudo\fR
+with user-controlled input.
+.PP
+Environment variables to be set for the command may also be passed
+on the command line in the form of
+\fIVAR\fR=\fIvalue\fR,
+e.g.,
+\fRLD_LIBRARY_PATH\fR=\fI/usr/local/pkg/lib\fR.
+Variables passed on the command line are subject to restrictions
+imposed by the security policy plugin.
+The
+\fIsudoers\fR
+policy subjects variables passed on the command line to the same
+restrictions as normal environment variables with one important
+exception.
+If the
+\fIsetenv\fR
+option is set in
+\fIsudoers\fR,
+the command to be run has the
+\fRSETENV\fR
+tag set or the command matched is
+\fRALL\fR,
+the user may set variables that would otherwise be forbidden.
+See
+sudoers(@mansectform@)
+for more information.
+.SH "COMMAND EXECUTION"
+When
+\fBsudo\fR
+executes a command, the security policy specifies the execution
+environment for the command.
+Typically, the real and effective user and group and IDs are set to
+match those of the target user, as specified in the password database,
+and the group vector is initialized based on the group database
+(unless the
+\fB\-P\fR
+option was specified).
+.PP
+The following parameters may be specified by security policy:
+.TP 3n
+\fB\(bu\fR
+real and effective user-ID
+.TP 3n
+\fB\(bu\fR
+real and effective group-ID
+.TP 3n
+\fB\(bu\fR
+supplementary group-IDs
+.TP 3n
+\fB\(bu\fR
+the environment list
+.TP 3n
+\fB\(bu\fR
+current working directory
+.TP 3n
+\fB\(bu\fR
+file creation mode mask (umask)
+.if \n(SL \{\
+.TP 3n
+\fB\(bu\fR
+SELinux role and type
+.\}
+.if \n(PS \{\
+.TP 3n
+\fB\(bu\fR
+Solaris project
+.\}
+.if \n(PS \{\
+.TP 3n
+\fB\(bu\fR
+Solaris privileges
+.\}
+.if \n(LC \{\
+.TP 3n
+\fB\(bu\fR
+BSD
+login class
+.\}
+.TP 3n
+\fB\(bu\fR
+scheduling priority (aka nice value)
+.SS "Process model"
+There are two distinct ways
+\fBsudo\fR
+can run a command.
+.PP
+If an I/O logging plugin is configured or if the security policy
+explicitly requests it, a new pseudo-terminal
+(\(lqpty\(rq)
+is allocated and
+fork(2)
+is used to create a second
+\fBsudo\fR
+process, referred to as the
+\fImonitor\fR.
+The
+\fImonitor\fR
+creates a new terminal session with itself as the leader and the pty as its
+controlling terminal, calls
+fork(2),
+sets up the execution environment as described above, and then uses the
+execve(2)
+system call to run the command in the child process.
+The
+\fImonitor\fR
+exists to relay job control signals between the user's
+existing terminal and the pty the command is being run in.
+This makes it possible to suspend and resume the command.
+Without the monitor, the command would be in what POSIX terms an
+\(lqorphaned process group\(rq
+and it would not receive any job control signals from the kernel.
+When the command exits or is terminated by a signal, the
+\fImonitor\fR
+passes the command's exit status to the main
+\fBsudo\fR
+process and exits.
+After receiving the command's exit status, the main
+\fBsudo\fR
+passes the command's exit status to the security policy's close function
+and exits.
+.PP
+If no pty is used,
+\fBsudo\fR
+calls
+fork(2),
+sets up the execution environment as described above, and uses the
+execve(2)
+system call to run the command in the child process.
+The main
+\fBsudo\fR
+process waits until the command has completed, then passes the
+command's exit status to the security policy's close function and exits.
+As a special case, if the policy plugin does not define a close
+function,
+\fBsudo\fR
+will execute the command directly instead of calling
+fork(2)
+first.
+The
+\fIsudoers\fR
+policy plugin will only define a close function when I/O logging
+is enabled, a pty is required, or the
+\fIpam_session\fR
+or
+\fIpam_setcred\fR
+options are enabled.
+Note that
+\fIpam_session\fR
+and
+\fIpam_setcred\fR
+are enabled by default on systems using PAM.
+.PP
+On systems that use PAM, the security policy's close function
+is responsible for closing the PAM session.
+It may also log the command's exit status.
+.SS "Signal handling"
+When the command is run as a child of the
+\fBsudo\fR
+process,
+\fBsudo\fR
+will relay signals it receives to the command.
+The
+\fRSIGINT\fR
+and
+\fRSIGQUIT\fR
+signals are only relayed when the command is being run in a new pty
+or when the signal was sent by a user process, not the kernel.
+This prevents the command from receiving
+\fRSIGINT\fR
+twice each time the user enters control-C.
+Some signals, such as
+\fRSIGSTOP\fR
+and
+\fRSIGKILL\fR,
+cannot be caught and thus will not be relayed to the command.
+As a general rule,
+\fRSIGTSTP\fR
+should be used instead of
+\fRSIGSTOP\fR
+when you wish to suspend a command being run by
+\fBsudo\fR.
+.PP
+As a special case,
+\fBsudo\fR
+will not relay signals that were sent by the command it is running.
+This prevents the command from accidentally killing itself.
+On some systems, the
+reboot(@mansectsu@)
+command sends
+\fRSIGTERM\fR
+to all non-system processes other than itself before rebooting
+the system.
+This prevents
+\fBsudo\fR
+from relaying the
+\fRSIGTERM\fR
+signal it received back to
+reboot(@mansectsu@),
+which might then exit before the system was actually rebooted,
+leaving it in a half-dead state similar to single user mode.
+Note, however, that this check only applies to the command run by
+\fBsudo\fR
+and not any other processes that the command may create.
+As a result, running a script that calls
+reboot(@mansectsu@)
+or
+shutdown(@mansectsu@)
+via
+\fBsudo\fR
+may cause the system to end up in this undefined state unless the
+reboot(@mansectsu@)
+or
+shutdown(@mansectsu@)
+are run using the
+\fBexec\fR()
+family of functions instead of
+\fBsystem\fR()
+(which interposes a shell between the command and the calling process).
+.PP
+If no I/O logging plugins are loaded and the policy plugin has not
+defined a
+\fBclose\fR()
+function, set a command timeout or required that the command be
+run in a new pty,
+\fBsudo\fR
+may execute the command directly instead of running it as a child process.
+.SS "Plugins"
+Plugins may be specified via
+\fRPlugin\fR
+directives in the
+sudo.conf(@mansectform@)
+file.
+They may be loaded as dynamic shared objects (on systems that support them),
+or compiled directly into the
+\fBsudo\fR
+binary.
+If no
+sudo.conf(@mansectform@)
+file is present, or if it doesn't contain any
+\fRPlugin\fR
+lines,
+\fBsudo\fR
+will use
+sudoers(@mansectform@)
+for the policy, auditing and I/O logging plugins.
+See the
+sudo.conf(@mansectform@)
+manual for details of the
+\fI@sysconfdir@/sudo.conf\fR
+file and the
+sudo_plugin(@mansectform@)
+manual for more information about the
+\fBsudo\fR
+plugin architecture.
+.SH "EXIT VALUE"
+Upon successful execution of a command, the exit status from
+\fBsudo\fR
+will be the exit status of the program that was executed.
+If the command terminated due to receipt of a signal,
+\fBsudo\fR
+will send itself the same signal that terminated the command.
+.PP
+If the
+\fB\-l\fR
+option was specified without a command,
+\fBsudo\fR
+will exit with a value of 0 if the user is allowed to run
+\fBsudo\fR
+and they authenticated successfully (as required by the security policy).
+If a command is specified with the
+\fB\-l\fR
+option, the exit value will only be 0 if the command is permitted by the
+security policy, otherwise it will be 1.
+.PP
+If there is an authentication failure, a configuration/permission
+problem or if the given command cannot be executed,
+\fBsudo\fR
+exits with a value of 1.
+In the latter case, the error string is printed to the standard error.
+If
+\fBsudo\fR
+cannot
+stat(2)
+one or more entries in the user's
+\fRPATH\fR,
+an error is printed to the standard error.
+(If the directory does not exist or if it is not really a directory,
+the entry is ignored and no error is printed.)
+This should not happen under normal circumstances.
+The most common reason for
+stat(2)
+to return
+\(lqpermission denied\(rq
+is if you are running an automounter and one of the directories in
+your
+\fRPATH\fR
+is on a machine that is currently unreachable.
+.SH "SECURITY NOTES"
+\fBsudo\fR
+tries to be safe when executing external commands.
+.PP
+To prevent command spoofing,
+\fBsudo\fR
+checks "." and "" (both denoting current directory) last when
+searching for a command in the user's
+\fRPATH\fR
+(if one or both are in the
+\fRPATH\fR).
+Note, however, that the actual
+\fRPATH\fR
+environment variable is
+\fInot\fR
+modified and is passed unchanged to the program that
+\fBsudo\fR
+executes.
+.PP
+Users should
+\fInever\fR
+be granted
+\fBsudo\fR
+privileges to execute files that are writable by the user or
+that reside in a directory that is writable by the user.
+If the user can modify or replace the command there is no way
+to limit what additional commands they can run.
+.PP
+Please note that
+\fBsudo\fR
+will normally only log the command it explicitly runs.
+If a user runs a command such as
+\fRsudo su\fR
+or
+\fRsudo sh\fR,
+subsequent commands run from that shell are not subject to
+\fBsudo\fR's
+security policy.
+The same is true for commands that offer shell escapes (including
+most editors).
+If I/O logging is enabled, subsequent commands will have their input and/or
+output logged, but there will not be traditional logs for those commands.
+Because of this, care must be taken when giving users access to commands via
+\fBsudo\fR
+to verify that the command does not inadvertently give the user an
+effective root shell.
+For more information, please see the
+\fIPreventing shell escapes\fR
+section in
+sudoers(@mansectform@).
+.PP
+To prevent the disclosure of potentially sensitive information,
+\fBsudo\fR
+disables core dumps by default while it is executing (they are
+re-enabled for the command that is run).
+This historical practice dates from a time when most operating
+systems allowed set-user-ID processes to dump core by default.
+To aid in debugging
+\fBsudo\fR
+crashes, you may wish to re-enable core dumps by setting
+\(lqdisable_coredump\(rq
+to false in the
+sudo.conf(@mansectform@)
+file as follows:
+.nf
+.sp
+.RS 6n
+Set disable_coredump false
+.RE
+.fi
+.PP
+See the
+sudo.conf(@mansectform@)
+manual for more information.
+.SH "ENVIRONMENT"
+\fBsudo\fR
+utilizes the following environment variables.
+The security policy has control over the actual content of the command's
+environment.
+.TP 17n
+\fREDITOR\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode if neither
+\fRSUDO_EDITOR\fR
+nor
+\fRVISUAL\fR
+is set.
+.TP 17n
+\fRMAIL\fR
+Set to the mail spool of the target user when the
+\fB\-i\fR
+option is specified or when
+\fIenv_reset\fR
+is enabled in
+\fIsudoers\fR
+(unless
+\fRMAIL\fR
+is present in the
+\fIenv_keep\fR
+list).
+.TP 17n
+\fRHOME\fR
+Set to the home directory of the target user when the
+\fB\-i\fR
+or
+\fB\-H\fR
+options are specified, when the
+\fB\-s\fR
+option is specified and
+\fIset_home\fR
+is set in
+\fIsudoers\fR,
+when
+\fIalways_set_home\fR
+is enabled in
+\fIsudoers\fR,
+or when
+\fIenv_reset\fR
+is enabled in
+\fIsudoers\fR
+and
+\fIHOME\fR
+is not present in the
+\fIenv_keep\fR
+list.
+.TP 17n
+\fRLOGNAME\fR
+Set to the login name of the target user when the
+\fB\-i\fR
+option is specified, when the
+\fIset_logname\fR
+option is enabled in
+\fIsudoers\fR
+or when the
+\fIenv_reset\fR
+option is enabled in
+\fIsudoers\fR
+(unless
+\fRLOGNAME\fR
+is present in the
+\fIenv_keep\fR
+list).
+.TP 17n
+\fRPATH\fR
+May be overridden by the security policy.
+.TP 17n
+\fRSHELL\fR
+Used to determine shell to run with
+\fB\-s\fR
+option.
+.TP 17n
+\fRSUDO_ASKPASS\fR
+Specifies the path to a helper program used to read the password
+if no terminal is available or if the
+\fB\-A\fR
+option is specified.
+.TP 17n
+\fRSUDO_COMMAND\fR
+Set to the command run by sudo, including command line arguments.
+The command line arguments are truncated at 4096 characters to
+prevent a potential execution error.
+.TP 17n
+\fRSUDO_EDITOR\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode.
+.TP 17n
+\fRSUDO_GID\fR
+Set to the group-ID of the user who invoked sudo.
+.TP 17n
+\fRSUDO_PROMPT\fR
+Used as the default password prompt unless
+the
+\fB\-p\fR
+option was specified.
+.TP 17n
+\fRSUDO_PS1\fR
+If set,
+\fRPS1\fR
+will be set to its value for the program being run.
+.TP 17n
+\fRSUDO_UID\fR
+Set to the user-ID of the user who invoked sudo.
+.TP 17n
+\fRSUDO_USER\fR
+Set to the login name of the user who invoked sudo.
+.TP 17n
+\fRUSER\fR
+Set to the same value as
+\fRLOGNAME\fR,
+described above.
+.TP 17n
+\fRVISUAL\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode if
+\fRSUDO_EDITOR\fR
+is not set.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+\fBsudo\fR
+front end configuration
+.SH "EXAMPLES"
+Note: the following examples assume a properly configured security
+policy.
+.PP
+To get a file listing of an unreadable directory:
+.nf
+.sp
+.RS 6n
+$ sudo ls /usr/local/protected
+.RE
+.fi
+.PP
+To list the home directory of user yaz on a machine where the file
+system holding ~yaz is not exported as root:
+.nf
+.sp
+.RS 6n
+$ sudo -u yaz ls ~yaz
+.RE
+.fi
+.PP
+To edit the
+\fIindex.html\fR
+file as user www:
+.nf
+.sp
+.RS 6n
+$ sudoedit -u www ~www/htdocs/index.html
+.RE
+.fi
+.PP
+To view system logs only accessible to root and users in the adm
+group:
+.nf
+.sp
+.RS 6n
+$ sudo -g adm more /var/log/syslog
+.RE
+.fi
+.PP
+To run an editor as jim with a different primary group:
+.nf
+.sp
+.RS 6n
+$ sudoedit -u jim -g audio ~jim/sound.txt
+.RE
+.fi
+.PP
+To shut down a machine:
+.nf
+.sp
+.RS 6n
+$ sudo shutdown -r +15 "quick reboot"
+.RE
+.fi
+.PP
+To make a usage listing of the directories in the /home partition.
+Note that this runs the commands in a sub-shell to make the
+\fRcd\fR
+and file redirection work.
+.nf
+.sp
+.RS 6n
+$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
+.RE
+.fi
+.SH "DIAGNOSTICS"
+Error messages produced by
+\fBsudo\fR
+include:
+.TP 6n
+\fRediting files in a writable directory is not permitted\fR
+By default,
+\fBsudoedit\fR
+does not permit editing a file when any of the parent directories are writable
+by the invoking user.
+This avoids a race condition that could allow the user to overwrite
+an arbitrary file.
+See the
+\fIsudoedit_checkdir\fR
+option in
+sudoers(@mansectform@)
+for more information.
+.TP 6n
+\fRediting symbolic links is not permitted\fR
+By default,
+\fBsudoedit\fR
+does not follow symbolic links when opening files.
+See the
+\fIsudoedit_follow\fR
+option in
+sudoers(@mansectform@)
+for more information.
+.TP 6n
+\fReffective uid is not 0, is sudo installed setuid root?\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary must be owned by the root user and have the set-user-ID bit set.
+Also, it must not be located on a file system mounted with the
+\(oqnosuid\(cq
+option or on an NFS file system that maps uid 0 to an unprivileged uid.
+.TP 6n
+\fReffective uid is not 0, is sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary has the proper owner and permissions but it still did not run
+with root privileges.
+The most common reason for this is that the file system the
+\fBsudo\fR
+binary is located on is mounted with the
+\(oqnosuid\(cq
+option or it is an NFS file system that maps uid 0 to an unprivileged uid.
+.TP 6n
+\fRfatal error, unable to load plugins\fR
+An error occurred while loading or initializing the plugins specified in
+sudo.conf(@mansectform@).
+.TP 6n
+\fRinvalid environment variable name\fR
+One or more environment variable names specified via the
+\fB\-E\fR
+option contained an equal sign
+(\(oq=\(cq).
+The arguments to the
+\fB\-E\fR
+option should be environment variable names without an associated value.
+.TP 6n
+\fRno password was provided\fR
+When
+\fBsudo\fR
+tried to read the password, it did not receive any characters.
+This may happen if no terminal is available (or the
+\fB\-S\fR
+option is specified) and the standard input has been redirected from
+\fI/dev/null\fR.
+.TP 6n
+\fRa terminal is required to read the password\fR
+\fBsudo\fR
+needs to read the password but there is no mechanism available for it
+to do so.
+A terminal is not present to read the password from,
+\fBsudo\fR
+has not been configured to read from the standard input,
+the
+\fB\-S\fR
+option was not used, and no askpass helper has been specified either via the
+sudo.conf(@mansectform@)
+file or the
+\fRSUDO_ASKPASS\fR
+environment variable.
+.TP 6n
+\fRno writable temporary directory found\fR
+\fBsudoedit\fR
+was unable to find a usable temporary directory in which to store its
+intermediate files.
+.TP 6n
+\fRsudo must be owned by uid 0 and have the setuid bit set\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary does not have the correct owner or permissions.
+It must be owned by the root user and have the set-user-ID bit set.
+.TP 6n
+\fRsudoedit is not supported on this platform\fR
+It is only possible to run
+\fBsudoedit\fR
+on systems that support setting the effective user-ID.
+.TP 6n
+\fRtimed out reading password\fR
+The user did not enter a password before the password timeout
+(5 minutes by default) expired.
+.TP 6n
+\fRyou do not exist in the passwd database\fR
+Your user-ID does not appear in the system passwd database.
+.TP 6n
+\fRyou may not specify environment variables in edit mode\fR
+It is only possible to specify environment variables when running
+a command.
+When editing a file, the editor is run with the user's environment unmodified.
+.SH "SEE ALSO"
+su(1),
+stat(2),
+login_cap(3),
+passwd(@mansectform@),
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudoers_timestamp(@mansectform@),
+sudoreplay(@mansectsu@),
+visudo(@mansectsu@)
+.SH "HISTORY"
+See the HISTORY file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+There is no easy way to prevent a user from gaining a root shell
+if that user is allowed to run arbitrary commands via
+\fBsudo\fR.
+Also, many programs (such as editors) allow the user to run commands
+via shell escapes, thus avoiding
+\fBsudo\fR's
+checks.
+However, on most systems it is possible to prevent shell escapes with the
+sudoers(@mansectform@)
+plugin's
+\fInoexec\fR
+functionality.
+.PP
+It is not meaningful to run the
+\fRcd\fR
+command directly via sudo, e.g.,
+.nf
+.sp
+.RS 6n
+$ sudo cd /usr/local/protected
+.RE
+.fi
+.PP
+since when the command exits the parent process (your shell) will
+still be the same.
+Please see the
+\fIEXAMPLES\fR
+section for more information.
+.PP
+Running shell scripts via
+\fBsudo\fR
+can expose the same kernel bugs that make set-user-ID shell scripts
+unsafe on some operating systems (if your OS has a /dev/fd/ directory,
+set-user-ID shell scripts are generally safe).
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo.man.in.sed b/doc/sudo.man.in.sed
new file mode 100644
index 0000000..432dd74
--- /dev/null
+++ b/doc/sudo.man.in.sed
@@ -0,0 +1,76 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+.nr BA @BAMAN@\
+.nr LC @LCMAN@\
+.nr PS @PSMAN@\
+\1/
+
+s/^\(\[\\fB\\-a\\fR.*\\fItype\\fR\]\) *$/.if \\n(BA \1/
+s/^\(\[\\fB\\-c\\fR.*\\fIclass\\fR\]\) *$/.if \\n(LC \1/
+s/^\(\[\\fB\\-r\\fR.*\\fIrole\\fR\]\) *$/.if \\n(SL \1/
+s/^\(\[\\fB\\-t\\fR.*\\fItype\\fR\]\) *$/.if \\n(SL \1/
+
+/^\.TP 12n$/ {
+ N
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/i\
+.if \\n(BA \\{\\
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/i\
+.if \\n(LC \\{\\
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/i\
+.if \\n(SL \\{\\
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/i\
+.if \\n(SL \\{\\
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/!i\
+.\\}
+ }
+ }
+}
+
+/^\.TP 3n$/ {
+ N
+ N
+ /^.TP 3n\n\\fB\\(bu\\fR\nSELinux role and type$/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nSolaris project$/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nSolaris privileges$/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nBSD$/ {
+ N
+ i\
+.if \\n(LC \\{\\
+ a\
+.\\}
+ }
+}
diff --git a/doc/sudo.mdoc.in b/doc/sudo.mdoc.in
new file mode 100644
index 0000000..fd2d205
--- /dev/null
+++ b/doc/sudo.mdoc.in
@@ -0,0 +1,1383 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2020
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.Dd September 1, 2020
+.Dt SUDO @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo ,
+.Nm sudoedit
+.Nd execute a command as another user
+.Sh SYNOPSIS
+.Nm sudo
+.Fl h | K | k | V
+.Nm sudo
+.Fl v
+.Op Fl ABknS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl u Ar user
+.Nm sudo
+.Fl l
+.Op Fl ABknS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl U Ar user
+.Op Fl u Ar user
+.Op Ar command
+.Nm sudo
+.Op Fl ABbEHnPS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl C Ar num
+.if \n(LC \{\
+.Op Fl c Ar class
+.\}
+.Op Fl D Ar directory
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl R Ar directory
+.if \n(SL \{\
+.Op Fl r Ar role
+.Op Fl t Ar type
+.\}
+.Op Fl T Ar timeout
+.Op Fl u Ar user
+.Op Ar VAR Ns = Ns Ar value
+.Op Fl i | s
+.Op Ar command
+.Nm sudoedit
+.Op Fl ABknS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl C Ar num
+.if \n(LC \{\
+.Op Fl c Ar class
+.\}
+.Op Fl D Ar directory
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl R Ar directory
+.if \n(SL \{\
+.Op Fl r Ar role
+.Op Fl t Ar type
+.\}
+.Op Fl T Ar timeout
+.Op Fl u Ar user
+.Ar
+.Sh DESCRIPTION
+.Nm
+allows a permitted user to execute a
+.Ar command
+as the superuser or another user, as specified by the security
+policy.
+The invoking user's real
+.Pq Em not No effective
+user-ID is used to determine the user name with which
+to query the security policy.
+.Pp
+.Nm
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+.Nm
+front end.
+The default security policy is
+.Em sudoers ,
+which is configured via the file
+.Pa @sysconfdir@/sudoers ,
+or via LDAP.
+See the
+.Sx Plugins
+section for more information.
+.Pp
+The security policy determines what privileges, if any, a user has
+to run
+.Nm .
+The policy may require that users authenticate themselves with a
+password or another authentication mechanism.
+If authentication is required,
+.Nm
+will exit if the user's password is not entered within a configurable
+time limit.
+This limit is policy-specific; the default password prompt timeout
+for the
+.Em sudoers
+security policy is
+.Li @password_timeout@
+minutes.
+.Pp
+Security policies may support credential caching to allow the user
+to run
+.Nm
+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.
+See the
+.Em timestamp_type
+and
+.Em timestamp_timeout
+options in
+.Xr sudoers @mansectform@
+for more information.
+By running
+.Nm
+with the
+.Fl v
+option, a user can update the cached credentials without running a
+.Ar command .
+.Pp
+On systems where
+.Nm
+is the primary method of gaining superuser privileges, it is imperative
+to avoid syntax errors in the security policy configuration files.
+For the default security policy,
+.Xr sudoers @mansectform@ ,
+changes to the configuration files should be made using the
+.Xr visudo @mansectsu@
+utility which will ensure that no syntax errors are introduced.
+.Pp
+When invoked as
+.Nm sudoedit ,
+the
+.Fl e
+option (described below), is implied.
+.Pp
+Security policies may log successful and failed attempts to use
+.Nm .
+If an I/O plugin is configured, the running command's input and
+output may be logged as well.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl A , -askpass
+Normally, if
+.Nm
+requires a password, it will read it from the user's terminal.
+If the
+.Fl A Pq Em askpass
+option is specified, a (possibly graphical) helper program is
+executed to read the user's password and output the password to the
+standard output.
+If the
+.Ev SUDO_ASKPASS
+environment variable is set, it specifies the path to the helper
+program.
+Otherwise, if
+.Xr sudo.conf @mansectform@
+contains a line specifying the askpass program, that value will be
+used.
+For example:
+.Bd -literal -offset 4n
+# Path to askpass helper program
+Path askpass /usr/X11R6/bin/ssh-askpass
+.Ed
+.Pp
+If no askpass program is available,
+.Nm
+will exit with an error.
+.if \n(BA \{\
+.It Fl a Ar type , Fl -auth-type Ns = Ns Ar type
+Use the specified
+.Bx
+authentication
+.Ar type
+when validating the user, if allowed by
+.Pa /etc/login.conf .
+The system administrator may specify a list of sudo-specific
+authentication methods by adding an
+.Dq auth-sudo
+entry in
+.Pa /etc/login.conf .
+This option is only available on systems that support
+.Bx
+authentication.
+.\}
+.It Fl B , -bell
+Ring the bell as part of the password promp when a terminal is present.
+This option has no effect if an askpass program is used.
+.It Fl b , -background
+Run the given command in the background.
+Note that it is not possible to use shell job control to manipulate
+background processes started by
+.Nm .
+Most interactive commands will fail to work properly in background
+mode.
+.It Fl C Ar num , Fl -close-from Ns = Ns Ar num
+Close all file descriptors greater than or equal to
+.Ar num
+before executing a command.
+Values less than three are not permitted.
+By default,
+.Nm
+will close all open file descriptors other than standard input,
+standard output and standard error when executing a command.
+The security policy may restrict the user's ability to use this option.
+The
+.Em sudoers
+policy only permits use of the
+.Fl C
+option when the administrator has enabled the
+.Em closefrom_override
+option.
+.if \n(LC \{\
+.It Fl c Ar class , Fl -login-class Ns = Ns Ar class
+Run the command with resource limits and scheduling priority of
+the specified login
+.Ar class .
+The
+.Ar class
+argument can be either a class name as defined in
+.Pa /etc/login.conf ,
+or a single
+.Ql \-
+character.
+If
+.Ar class
+is
+.Cm - ,
+the default login class of the target user will be used.
+Otherwise, the command must be run as the superuser (user-ID 0), or
+.Nm
+must be run from a shell that is already running as the superuser.
+If the command is being run as a login shell, additional
+.Pa /etc/login.conf
+settings, such as the umask and environment variables, will
+be applied, if present.
+This option is only available on systems with
+.Bx
+login classes.
+.\}
+.It Fl D Ar directory , Fl -chdir Ns = Ns Ar directory
+Run the command in the specified
+.Ar directory
+instead of the current working directory.
+The security policy may return an error if the user does not have
+permission to specify the working directory.
+.It Fl E , -preserve-env
+Indicates to the security policy that the user wishes to
+preserve their existing environment variables.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+.It Fl -preserve-env=list
+Indicates to the security policy that the user wishes to add the
+comma-separated list of environment variables to those preserved
+from the user's environment.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+This option may be specified multiple times.
+.It Fl e , -edit
+Edit one or more files instead of running a command.
+In lieu of a path name, the string "sudoedit" is used when consulting
+the security policy.
+If the user is authorized by the policy, the following steps are
+taken:
+.Bl -enum -offset 4
+.It
+Temporary copies are made of the files to be edited with the owner
+set to the invoking user.
+.It
+The editor specified by the policy is run to edit the temporary
+files.
+The
+.Em sudoers
+policy uses the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+and
+.Ev EDITOR
+environment variables (in that order).
+If none of
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+are set, the first program listed in the
+.Em editor
+.Xr sudoers @mansectform@
+option is used.
+.It
+If they have been modified, the temporary files are copied back to
+their original location and the temporary versions are removed.
+.El
+.Pp
+To help prevent the editing of unauthorized files, the following
+restrictions are enforced unless explicitly allowed by the security policy:
+.Bl -bullet -offset 4 -width 1n
+.It
+Symbolic links may not be edited (version 1.8.15 and higher).
+.It
+Symbolic links along the path to be edited are not followed when the
+parent directory is writable by the invoking user unless that user
+is root (version 1.8.16 and higher).
+.It
+Files located in a directory that is writable by the invoking user may
+not be edited unless that user is root (version 1.8.16 and higher).
+.El
+.Pp
+Users are never allowed to edit device special files.
+.Pp
+If the specified file does not exist, it will be created.
+Note that unlike most commands run by
+.Em sudo ,
+the editor is run with the invoking user's environment unmodified.
+If the temporary file becomes empty after editing, the user will
+be prompted before it is installed.
+If, for some reason,
+.Nm
+is unable to update a file with its edited version, the user will
+receive a warning and the edited copy will remain in a temporary
+file.
+.It Fl g Ar group , Fl -group Ns = Ns Ar group
+Run the command with the primary group set to
+.Ar group
+instead of the primary group specified by the target
+user's password database entry.
+The
+.Ar group
+may be either a group name or a numeric group-ID
+.Pq GID
+prefixed with the
+.Ql #
+character (e.g.,
+.Li #0
+for GID 0).
+When running a command as a GID, many shells require that the
+.Ql #
+be escaped with a backslash
+.Pq Ql \e .
+If no
+.Fl u
+option is specified, the command will be run as the invoking user.
+In either case, the primary group will be set to
+.Ar group .
+The
+.Em sudoers
+policy permits any of the target user's groups to be specified via
+the
+.Fl g
+option as long as the
+.Fl P
+option is not in use.
+.It Fl H , -set-home
+Request that the security policy set the
+.Ev HOME
+environment variable to the home directory specified by the target
+user's password database entry.
+Depending on the policy, this may be the default behavior.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl h Ar host , Fl -host Ns = Ns Ar host
+Run the command on the specified
+.Ar host
+if the security policy plugin supports remote commands.
+Note that the
+.Em sudoers
+plugin does not currently support running remote commands.
+This may also be used in conjunction with the
+.Fl l
+option to list a user's privileges for the remote host.
+.It Fl i , -login
+Run the shell specified by the target user's password database entry
+as a login shell.
+This means that login-specific resource files such as
+.Pa .profile ,
+.Pa .bash_profile
+or
+.Pa .login
+will be read by the shell.
+If a command is specified, it is passed to the shell for execution
+via the shell's
+.Fl c
+option.
+If no command is specified, an interactive shell is executed.
+.Nm
+attempts to change to that user's home directory before running the
+shell.
+The command is run with an environment similar to the one
+a user would receive at log in.
+Note that most shells behave differently when a command is specified
+as compared to an interactive session; consult the shell's manual
+for details.
+The
+.Em Command environment
+section in the
+.Xr sudoers @mansectform@
+manual documents how the
+.Fl i
+option affects the environment in which a command is run when the
+.Em sudoers
+policy is in use.
+.It Fl K , -remove-timestamp
+Similar to the
+.Fl k
+option, except that it removes the user's cached credentials entirely
+and may not be used in conjunction with a command or other option.
+This option does not require a password.
+Not all security policies support credential caching.
+.It Fl k , -reset-timestamp
+When used without a command, invalidates the user's cached credentials.
+In other words, the next time
+.Nm
+is run a password will be required.
+This option does not require a password and was added to allow a
+user to revoke
+.Nm
+permissions from a
+.Pa .logout
+file.
+.Pp
+When used in conjunction with a command or an option that may require
+a password, this option will cause
+.Nm
+to ignore the user's cached credentials.
+As a result,
+.Nm
+will prompt for a password (if one is required by the security
+policy) and will not update the user's cached credentials.
+.Pp
+Not all security policies support credential caching.
+.It Fl l , Fl -list
+If no
+.Ar command
+is specified,
+list the allowed (and forbidden) commands for the
+invoking user (or the user specified by the
+.Fl U
+option) on the current host.
+A longer list format is used if this option is specified multiple times
+and the security policy supports a verbose output format.
+.Pp
+If a
+.Ar command
+is specified and is permitted by the security policy, the fully-qualified
+path to the command is displayed along with any command line
+arguments.
+If a
+.Ar command
+is specified but not allowed by the policy,
+.Nm
+will exit with a status value of 1.
+.It Fl n , -non-interactive
+Avoid prompting the user for input of any kind.
+If a password is required for the command to run,
+.Nm
+will display an error message and exit.
+.It Fl P , -preserve-groups
+Preserve the invoking user's group vector unaltered.
+By default, the
+.Em sudoers
+policy will initialize the group vector to the list of groups the
+target user is a member of.
+The real and effective group-IDs, however, are still set to match
+the target user.
+.It Fl p Ar prompt , Fl -prompt Ns = Ns Ar prompt
+Use a custom password prompt with optional escape sequences.
+The following percent
+.Pq Ql %
+escape sequences are supported by the
+.Em sudoers
+policy:
+.Bl -tag -width 2n
+.It Li %H
+expanded to the host name including the domain name (on if the
+machine's host name is fully qualified or the
+.Em fqdn
+option is set in
+.Xr sudoers @mansectform@ )
+.It Li %h
+expanded to the local host name without the domain name
+.It Li %p
+expanded to the name of the user whose password is being requested
+(respects the
+.Em rootpw ,
+.Em targetpw ,
+and
+.Em runaspw
+flags in
+.Xr sudoers @mansectform@ )
+.It Li \&%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
+expanded to the invoking user's login name
+.It Li %%
+two consecutive
+.Ql %
+characters are collapsed into a single
+.Ql %
+character
+.El
+.Pp
+The custom prompt will override the default prompt specified by either
+the security policy or the
+.Ev SUDO_PROMPT
+environment variable.
+On systems that use PAM, the custom prompt will also override the prompt
+specified by a PAM module unless the
+.Em passprompt_override
+flag is disabled in
+.Em sudoers .
+.It Fl R Ar directory , Fl -chroot Ns = Ns Ar directory
+Change to the specified root
+.Ar directory
+(see
+.Xr chroot @mansectsu@ )
+before running the command.
+The security policy may return an error if the user does not have
+permission to specify the root directory.
+.if \n(SL \{\
+.It Fl r Ar role , Fl -role Ns = Ns Ar role
+Run the command with an SELinux security context that includes
+the specified
+.Ar role .
+.\}
+.It Fl S , -stdin
+Write the prompt to the standard error and read the password from the
+standard input instead of using the terminal device.
+.It Fl s , -shell
+Run the shell specified by the
+.Ev SHELL
+environment variable if it is set or the shell specified by the
+invoking user's password database entry.
+If a command is specified, it is passed to the shell for execution
+via the shell's
+.Fl c
+option.
+If no command is specified, an interactive shell is executed.
+Note that most shells behave differently when a command is specified
+as compared to an interactive session; consult the shell's manual
+for details.
+.if \n(SL \{\
+.It Fl t Ar type , Fl -type Ns = Ns Ar type
+Run the command with an SELinux security context that includes
+the specified
+.Ar type .
+If no
+.Ar type
+is specified, the default type is derived from the role.
+.\}
+.It Fl U Ar user , Fl -other-user Ns = Ns Ar user
+Used in conjunction with the
+.Fl l
+option to list the privileges for
+.Ar user
+instead of for the invoking user.
+The security policy may restrict listing other users' privileges.
+The
+.Em sudoers
+policy only allows root or a user with the
+.Li ALL
+privilege on the current host to use this option.
+.It Fl T Ar timeout , Fl -command-timeout Ns = Ns Ar timeout
+Used to set a timeout for the command.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The security policy may restrict the ability to set command timeouts.
+The
+.Em sudoers
+policy requires that user-specified timeouts be explicitly enabled.
+.It Fl u Ar user , Fl -user Ns = Ns Ar user
+Run the command as a user other than the default target user
+(usually
+.Em root ) .
+The
+.Ar user
+may be either a user name or a numeric user-ID
+.Pq UID
+prefixed with the
+.Ql #
+character (e.g.,
+.Li #0
+for UID 0).
+When running commands as a UID, many shells require that the
+.Ql #
+be escaped with a backslash
+.Pq Ql \e .
+Some security policies may restrict UIDs
+to those listed in the password database.
+The
+.Em sudoers
+policy allows UIDs that are not in the password database as long as the
+.Em targetpw
+option is not set.
+Other security policies may not support this.
+.It Fl V , -version
+Print the
+.Nm
+version string as well as the version string of the security
+policy plugin and any I/O plugins.
+If the invoking user is already root the
+.Fl V
+option will display the arguments passed to configure when
+.Nm
+was built and plugins may display more verbose information such as
+default options.
+.It Fl v , -validate
+Update the user's cached credentials, authenticating the user
+if necessary.
+For the
+.Em sudoers
+plugin, this extends the
+.Nm
+timeout for another
+.Li @timeout@
+minutes by default, but does not run a command.
+Not all security policies support cached credentials.
+.It Fl -
+The
+.Fl -
+option indicates that
+.Nm
+should stop processing command line arguments.
+.El
+.Pp
+Options that take a value may only be specified once unless
+otherwise indicated in the description.
+This is to help guard against problems caused by poorly written
+scripts that invoke
+.Nm sudo
+with user-controlled input.
+.Pp
+Environment variables to be set for the command may also be passed
+on the command line in the form of
+.Ar VAR Ns = Ns Ar value ,
+e.g.,
+.Ev LD_LIBRARY_PATH Ns = Ns Pa /usr/local/pkg/lib .
+Variables passed on the command line are subject to restrictions
+imposed by the security policy plugin.
+The
+.Em sudoers
+policy subjects variables passed on the command line to the same
+restrictions as normal environment variables with one important
+exception.
+If the
+.Em setenv
+option is set in
+.Em sudoers ,
+the command to be run has the
+.Li SETENV
+tag set or the command matched is
+.Li ALL ,
+the user may set variables that would otherwise be forbidden.
+See
+.Xr sudoers @mansectform@
+for more information.
+.Sh COMMAND EXECUTION
+When
+.Nm
+executes a command, the security policy specifies the execution
+environment for the command.
+Typically, the real and effective user and group and IDs are set to
+match those of the target user, as specified in the password database,
+and the group vector is initialized based on the group database
+(unless the
+.Fl P
+option was specified).
+.Pp
+The following parameters may be specified by security policy:
+.Bl -bullet -width 1n
+.It
+real and effective user-ID
+.It
+real and effective group-ID
+.It
+supplementary group-IDs
+.It
+the environment list
+.It
+current working directory
+.It
+file creation mode mask (umask)
+.if \n(SL \{\
+.It
+SELinux role and type
+.\}
+.if \n(PS \{\
+.It
+Solaris project
+.It
+Solaris privileges
+.\}
+.if \n(LC \{\
+.It
+.Bx
+login class
+.\}
+.It
+scheduling priority (aka nice value)
+.El
+.Ss Process model
+There are two distinct ways
+.Nm
+can run a command.
+.Pp
+If an I/O logging plugin is configured or if the security policy
+explicitly requests it, a new pseudo-terminal
+.Pq Dq pty
+is allocated and
+.Xr fork 2
+is used to create a second
+.Nm
+process, referred to as the
+.Em monitor .
+The
+.Em monitor
+creates a new terminal session with itself as the leader and the pty as its
+controlling terminal, calls
+.Xr fork 2 ,
+sets up the execution environment as described above, and then uses the
+.Xr execve 2
+system call to run the command in the child process.
+The
+.Em monitor
+exists to relay job control signals between the user's
+existing terminal and the pty the command is being run in.
+This makes it possible to suspend and resume the command.
+Without the monitor, the command would be in what POSIX terms an
+.Dq orphaned process group
+and it would not receive any job control signals from the kernel.
+When the command exits or is terminated by a signal, the
+.Em monitor
+passes the command's exit status to the main
+.Nm
+process and exits.
+After receiving the command's exit status, the main
+.Nm
+passes the command's exit status to the security policy's close function
+and exits.
+.Pp
+If no pty is used,
+.Nm
+calls
+.Xr fork 2 ,
+sets up the execution environment as described above, and uses the
+.Xr execve 2
+system call to run the command in the child process.
+The main
+.Nm
+process waits until the command has completed, then passes the
+command's exit status to the security policy's close function and exits.
+As a special case, if the policy plugin does not define a close
+function,
+.Nm
+will execute the command directly instead of calling
+.Xr fork 2
+first.
+The
+.Em sudoers
+policy plugin will only define a close function when I/O logging
+is enabled, a pty is required, or the
+.Em pam_session
+or
+.Em pam_setcred
+options are enabled.
+Note that
+.Em pam_session
+and
+.Em pam_setcred
+are enabled by default on systems using PAM.
+.Pp
+On systems that use PAM, the security policy's close function
+is responsible for closing the PAM session.
+It may also log the command's exit status.
+.Ss Signal handling
+When the command is run as a child of the
+.Nm
+process,
+.Nm
+will relay signals it receives to the command.
+The
+.Dv SIGINT
+and
+.Dv SIGQUIT
+signals are only relayed when the command is being run in a new pty
+or when the signal was sent by a user process, not the kernel.
+This prevents the command from receiving
+.Dv SIGINT
+twice each time the user enters control-C.
+Some signals, such as
+.Dv SIGSTOP
+and
+.Dv SIGKILL ,
+cannot be caught and thus will not be relayed to the command.
+As a general rule,
+.Dv SIGTSTP
+should be used instead of
+.Dv SIGSTOP
+when you wish to suspend a command being run by
+.Nm .
+.Pp
+As a special case,
+.Nm
+will not relay signals that were sent by the command it is running.
+This prevents the command from accidentally killing itself.
+On some systems, the
+.Xr reboot @mansectsu@
+command sends
+.Dv SIGTERM
+to all non-system processes other than itself before rebooting
+the system.
+This prevents
+.Nm
+from relaying the
+.Dv SIGTERM
+signal it received back to
+.Xr reboot @mansectsu@ ,
+which might then exit before the system was actually rebooted,
+leaving it in a half-dead state similar to single user mode.
+Note, however, that this check only applies to the command run by
+.Nm
+and not any other processes that the command may create.
+As a result, running a script that calls
+.Xr reboot @mansectsu@
+or
+.Xr shutdown @mansectsu@
+via
+.Nm
+may cause the system to end up in this undefined state unless the
+.Xr reboot @mansectsu@
+or
+.Xr shutdown @mansectsu@
+are run using the
+.Fn exec
+family of functions instead of
+.Fn system
+(which interposes a shell between the command and the calling process).
+.Pp
+If no I/O logging plugins are loaded and the policy plugin has not
+defined a
+.Fn close
+function, set a command timeout or required that the command be
+run in a new pty,
+.Nm
+may execute the command directly instead of running it as a child process.
+.Ss Plugins
+Plugins may be specified via
+.Li Plugin
+directives in the
+.Xr sudo.conf @mansectform@
+file.
+They may be loaded as dynamic shared objects (on systems that support them),
+or compiled directly into the
+.Nm
+binary.
+If no
+.Xr sudo.conf @mansectform@
+file is present, or if it doesn't contain any
+.Li Plugin
+lines,
+.Nm
+will use
+.Xr sudoers @mansectform@
+for the policy, auditing and I/O logging plugins.
+See the
+.Xr sudo.conf @mansectform@
+manual for details of the
+.Pa @sysconfdir@/sudo.conf
+file and the
+.Xr sudo_plugin @mansectform@
+manual for more information about the
+.Nm
+plugin architecture.
+.Sh EXIT VALUE
+Upon successful execution of a command, the exit status from
+.Nm
+will be the exit status of the program that was executed.
+If the command terminated due to receipt of a signal,
+.Nm
+will send itself the same signal that terminated the command.
+.Pp
+If the
+.Fl l
+option was specified without a command,
+.Nm
+will exit with a value of 0 if the user is allowed to run
+.Nm
+and they authenticated successfully (as required by the security policy).
+If a command is specified with the
+.Fl l
+option, the exit value will only be 0 if the command is permitted by the
+security policy, otherwise it will be 1.
+.Pp
+If there is an authentication failure, a configuration/permission
+problem or if the given command cannot be executed,
+.Nm
+exits with a value of 1.
+In the latter case, the error string is printed to the standard error.
+If
+.Nm
+cannot
+.Xr stat 2
+one or more entries in the user's
+.Ev PATH ,
+an error is printed to the standard error.
+(If the directory does not exist or if it is not really a directory,
+the entry is ignored and no error is printed.)
+This should not happen under normal circumstances.
+The most common reason for
+.Xr stat 2
+to return
+.Dq permission denied
+is if you are running an automounter and one of the directories in
+your
+.Ev PATH
+is on a machine that is currently unreachable.
+.Sh SECURITY NOTES
+.Nm
+tries to be safe when executing external commands.
+.Pp
+To prevent command spoofing,
+.Nm
+checks "." and "" (both denoting current directory) last when
+searching for a command in the user's
+.Ev PATH
+(if one or both are in the
+.Ev PATH ) .
+Note, however, that the actual
+.Ev PATH
+environment variable is
+.Em not
+modified and is passed unchanged to the program that
+.Nm
+executes.
+.Pp
+Users should
+.Em never
+be granted
+.Nm
+privileges to execute files that are writable by the user or
+that reside in a directory that is writable by the user.
+If the user can modify or replace the command there is no way
+to limit what additional commands they can run.
+.Pp
+Please note that
+.Nm
+will normally only log the command it explicitly runs.
+If a user runs a command such as
+.Li sudo su
+or
+.Li sudo sh ,
+subsequent commands run from that shell are not subject to
+.Nm sudo Ns 's
+security policy.
+The same is true for commands that offer shell escapes (including
+most editors).
+If I/O logging is enabled, subsequent commands will have their input and/or
+output logged, but there will not be traditional logs for those commands.
+Because of this, care must be taken when giving users access to commands via
+.Nm
+to verify that the command does not inadvertently give the user an
+effective root shell.
+For more information, please see the
+.Em Preventing shell escapes
+section in
+.Xr sudoers @mansectform@ .
+.Pp
+To prevent the disclosure of potentially sensitive information,
+.Nm
+disables core dumps by default while it is executing (they are
+re-enabled for the command that is run).
+This historical practice dates from a time when most operating
+systems allowed set-user-ID processes to dump core by default.
+To aid in debugging
+.Nm
+crashes, you may wish to re-enable core dumps by setting
+.Dq disable_coredump
+to false in the
+.Xr sudo.conf @mansectform@
+file as follows:
+.Bd -literal -offset indent
+Set disable_coredump false
+.Ed
+.Pp
+See the
+.Xr sudo.conf @mansectform@
+manual for more information.
+.Sh ENVIRONMENT
+.Nm
+utilizes the following environment variables.
+The security policy has control over the actual content of the command's
+environment.
+.Bl -tag -width 15n
+.It Ev EDITOR
+Default editor to use in
+.Fl e
+(sudoedit) mode if neither
+.Ev SUDO_EDITOR
+nor
+.Ev VISUAL
+is set.
+.It Ev MAIL
+Set to the mail spool of the target user when the
+.Fl i
+option is specified or when
+.Em env_reset
+is enabled in
+.Em sudoers
+(unless
+.Ev MAIL
+is present in the
+.Em env_keep
+list).
+.It Ev HOME
+Set to the home directory of the target user when the
+.Fl i
+or
+.Fl H
+options are specified, when the
+.Fl s
+option is specified and
+.Em set_home
+is set in
+.Em sudoers ,
+when
+.Em always_set_home
+is enabled in
+.Em sudoers ,
+or when
+.Em env_reset
+is enabled in
+.Em sudoers
+and
+.Em HOME
+is not present in the
+.Em env_keep
+list.
+.It Ev LOGNAME
+Set to the login name of the target user when the
+.Fl i
+option is specified, when the
+.Em set_logname
+option is enabled in
+.Em sudoers
+or when the
+.Em env_reset
+option is enabled in
+.Em sudoers
+(unless
+.Ev LOGNAME
+is present in the
+.Em env_keep
+list).
+.It Ev PATH
+May be overridden by the security policy.
+.It Ev SHELL
+Used to determine shell to run with
+.Fl s
+option.
+.It Ev SUDO_ASKPASS
+Specifies the path to a helper program used to read the password
+if no terminal is available or if the
+.Fl A
+option is specified.
+.It Ev SUDO_COMMAND
+Set to the command run by sudo, including command line arguments.
+The command line arguments are truncated at 4096 characters to
+prevent a potential execution error.
+.It Ev SUDO_EDITOR
+Default editor to use in
+.Fl e
+(sudoedit) mode.
+.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
+.Fl p
+option was specified.
+.It Ev SUDO_PS1
+If set,
+.Ev PS1
+will be set to its value for the program being run.
+.It Ev SUDO_UID
+Set to the user-ID of the user who invoked sudo.
+.It Ev SUDO_USER
+Set to the login name of the user who invoked sudo.
+.It Ev USER
+Set to the same value as
+.Ev LOGNAME ,
+described above.
+.It Ev VISUAL
+Default editor to use in
+.Fl e
+(sudoedit) mode if
+.Ev SUDO_EDITOR
+is not set.
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+.Nm
+front end configuration
+.El
+.Sh EXAMPLES
+Note: the following examples assume a properly configured security
+policy.
+.Pp
+To get a file listing of an unreadable directory:
+.Bd -literal -offset indent
+$ sudo ls /usr/local/protected
+.Ed
+.Pp
+To list the home directory of user yaz on a machine where the file
+system holding ~yaz is not exported as root:
+.Bd -literal -offset indent
+$ sudo -u yaz ls ~yaz
+.Ed
+.Pp
+To edit the
+.Pa index.html
+file as user www:
+.Bd -literal -offset indent
+$ sudoedit -u www ~www/htdocs/index.html
+.Ed
+.Pp
+To view system logs only accessible to root and users in the adm
+group:
+.Bd -literal -offset indent
+$ sudo -g adm more /var/log/syslog
+.Ed
+.Pp
+To run an editor as jim with a different primary group:
+.Bd -literal -offset indent
+$ sudoedit -u jim -g audio ~jim/sound.txt
+.Ed
+.Pp
+To shut down a machine:
+.Bd -literal -offset indent
+$ sudo shutdown -r +15 "quick reboot"
+.Ed
+.Pp
+To make a usage listing of the directories in the /home partition.
+Note that this runs the commands in a sub-shell to make the
+.Li cd
+and file redirection work.
+.Bd -literal -offset indent
+$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
+.Ed
+.Sh DIAGNOSTICS
+Error messages produced by
+.Nm
+include:
+.Bl -tag -width 4n
+.It Li editing files in a writable directory is not permitted
+By default,
+.Nm sudoedit
+does not permit editing a file when any of the parent directories are writable
+by the invoking user.
+This avoids a race condition that could allow the user to overwrite
+an arbitrary file.
+See the
+.Em sudoedit_checkdir
+option in
+.Xr sudoers @mansectform@
+for more information.
+.It Li editing symbolic links is not permitted
+By default,
+.Nm sudoedit
+does not follow symbolic links when opening files.
+See the
+.Em sudoedit_follow
+option in
+.Xr sudoers @mansectform@
+for more information.
+.It Li effective uid is not 0, is sudo installed setuid root?
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary must be owned by the root user and have the set-user-ID bit set.
+Also, it must not be located on a file system mounted with the
+.Sq nosuid
+option or on an NFS file system that maps uid 0 to an unprivileged uid.
+.It Li effective uid is not 0, is sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary has the proper owner and permissions but it still did not run
+with root privileges.
+The most common reason for this is that the file system the
+.Nm
+binary is located on is mounted with the
+.Sq nosuid
+option or it is an NFS file system that maps uid 0 to an unprivileged uid.
+.It Li fatal error, unable to load plugins
+An error occurred while loading or initializing the plugins specified in
+.Xr sudo.conf @mansectform@ .
+.It Li invalid environment variable name
+One or more environment variable names specified via the
+.Fl E
+option contained an equal sign
+.Pq Ql = .
+The arguments to the
+.Fl E
+option should be environment variable names without an associated value.
+.It Li no password was provided
+When
+.Nm
+tried to read the password, it did not receive any characters.
+This may happen if no terminal is available (or the
+.Fl S
+option is specified) and the standard input has been redirected from
+.Pa /dev/null .
+.It Li a terminal is required to read the password
+.Nm
+needs to read the password but there is no mechanism available for it
+to do so.
+A terminal is not present to read the password from,
+.Nm
+has not been configured to read from the standard input,
+the
+.Fl S
+option was not used, and no askpass helper has been specified either via the
+.Xr sudo.conf @mansectform@
+file or the
+.Ev SUDO_ASKPASS
+environment variable.
+.It Li no writable temporary directory found
+.Nm sudoedit
+was unable to find a usable temporary directory in which to store its
+intermediate files.
+.It Li sudo must be owned by uid 0 and have the setuid bit set
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary does not have the correct owner or permissions.
+It must be owned by the root user and have the set-user-ID bit set.
+.It Li sudoedit is not supported on this platform
+It is only possible to run
+.Nm sudoedit
+on systems that support setting the effective user-ID.
+.It Li timed out reading password
+The user did not enter a password before the password timeout
+(5 minutes by default) expired.
+.It Li you do not exist in the passwd database
+Your user-ID does not appear in the system passwd database.
+.It Li you may not specify environment variables in edit mode
+It is only possible to specify environment variables when running
+a command.
+When editing a file, the editor is run with the user's environment unmodified.
+.El
+.Sh SEE ALSO
+.Xr su 1 ,
+.Xr stat 2 ,
+.Xr login_cap 3 ,
+.Xr passwd @mansectform@ ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudoers_timestamp @mansectform@ ,
+.Xr sudoreplay @mansectsu@ ,
+.Xr visudo @mansectsu@
+.Sh HISTORY
+See the HISTORY file in the
+.Nm
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.Sh AUTHORS
+Many people have worked on
+.Nm
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm .
+.Sh CAVEATS
+There is no easy way to prevent a user from gaining a root shell
+if that user is allowed to run arbitrary commands via
+.Nm .
+Also, many programs (such as editors) allow the user to run commands
+via shell escapes, thus avoiding
+.Nm sudo Ns 's
+checks.
+However, on most systems it is possible to prevent shell escapes with the
+.Xr sudoers @mansectform@
+plugin's
+.Em noexec
+functionality.
+.Pp
+It is not meaningful to run the
+.Li cd
+command directly via sudo, e.g.,
+.Bd -literal -offset indent
+$ sudo cd /usr/local/protected
+.Ed
+.Pp
+since when the command exits the parent process (your shell) will
+still be the same.
+Please see the
+.Sx EXAMPLES
+section for more information.
+.Pp
+Running shell scripts via
+.Nm
+can expose the same kernel bugs that make set-user-ID shell scripts
+unsafe on some operating systems (if your OS has a /dev/fd/ directory,
+set-user-ID shell scripts are generally safe).
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrv.proto.man.in b/doc/sudo_logsrv.proto.man.in
new file mode 100644
index 0000000..32c67c5
--- /dev/null
+++ b/doc/sudo_logsrv.proto.man.in
@@ -0,0 +1,899 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.TH "SUDO_LOGSRV.PROTO" "@mansectform@" "November 6, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrv.proto\fR
+\- Sudo log server protocol
+.SH "DESCRIPTION"
+Starting with version 1.9.0,
+\fBsudo\fR
+supports sending event and I/O logs to a log server.
+The protocol used is written in Google's Protocol Buffers domain
+specific language.
+The
+\fIEXAMPLES\fR
+section includes a complete description of the protocol in Protocol
+Buffers format.
+.PP
+Because there is no way to determine message boundaries when using
+Protocol Buffers, the wire size of each message is sent immediately
+preceding the message itself as a 32-bit unsigned integer in network
+byte order.
+This is referred to as
+\(lqlength-prefix framing\(rq
+and is how Google suggests handling the lack of message delimiters.
+.PP
+The protocol is made up of two basic messages,
+\fIClientMessage\fR
+and
+\fIServerMessage\fR,
+described below.
+The server must accept messages up to two megabytes in size.
+The server may return an error if the client tries to send a message
+larger than two megabytes.
+.SH "Client Messages"
+A
+\fIClientMessage\fR
+is a container used to encapsulate all the possible message types
+a client may send to the server.
+.nf
+.sp
+.RS 0n
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ ClientHello hello_msg = 13;
+ }
+}
+.RE
+.fi
+.PP
+The different
+\fIClientMessage\fR
+sub-messages the client may sent to the server are described below.
+.SS "TimeSpec"
+.nf
+.RS 0n
+message TimeSpec {
+ int64 tv_sec = 1;
+ int32 tv_nsec = 2;
+}
+.RE
+.fi
+.PP
+A
+\fITimeSpec\fR
+is the equivalent of a POSIX
+\fRstruct timespec\fR,
+containing seconds and nanoseconds members.
+The
+\fItv_sec\fR
+member is a 64-bit integer to support dates after the year 2038.
+.SS "InfoMessage"
+.nf
+.RS 0n
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+.RE
+.fi
+.PP
+An
+\fIInfoMessage\fR
+is used to represent information about the invoking user as well as the
+execution environment the command runs in the form of key-value pairs.
+The key is always a string but the value may be a 64-bit integer,
+a string, an array of strings or an array of 64-bit integers.
+The event log data is composed of
+\fIInfoMessage\fR
+entries.
+See the
+\fIEVENT LOG VARIABLES\fR
+section for more information.
+.SS "ClientHello hello_msg"
+.nf
+.RS 0n
+message ClientHello {
+ string client_id = 1;
+}
+.RE
+.fi
+.PP
+A
+\fIClientHello\fR
+message consists of client information that may be sent to the
+server when the client first connects.
+.TP 8n
+client_id
+A free-form client description.
+This usually includes the name and version of the client implementation.
+.SS "AcceptMessage accept_msg"
+.nf
+.RS 0n
+message AcceptMessage {
+ TimeSpec submit_time = 1;
+ repeated InfoMessage info_msgs = 2;
+ bool expect_iobufs = 3;
+}
+.RE
+.fi
+.PP
+An
+\fIAcceptMessage\fR
+is sent by the client when a command is allowed by the security policy.
+It contains the following members:
+.TP 8n
+submit_time
+The wall clock time when the command was submitted to the security policy.
+.TP 8n
+info_msgs
+An array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry and may also be
+used by server to determine where and how the I/O log is stored.
+.TP 8n
+expect_iobufs
+Set to true if the server should expect
+\fIIoBuffer\fR
+messages to follow (for I/O logging) or false if the server should only
+store the event log.
+.PP
+If an
+\fIAcceptMessage\fR
+is sent, the client must not send a
+\fIRejectMessage\fR
+or
+\fIRestartMessage\fR.
+.SS "RejectMessage reject_msg"
+.nf
+.RS 0n
+message RejectMessage {
+ TimeSpec submit_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.RE
+.fi
+.PP
+A
+\fIRejectMessage\fR
+is sent by the client when a command is denied by the security policy.
+It contains the following members:
+.TP 8n
+submit_time
+The wall clock time when the command was submitted to the security policy.
+.TP 8n
+reason
+The reason the security policy gave for denying the command.
+.TP 8n
+info_msgs
+An array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.PP
+If a
+\fIRejectMessage\fR
+is sent, the client must not send an
+\fIAcceptMessage\fR
+or
+\fIRestartMessage\fR.
+.SS "ExitMessage exit_msg"
+.nf
+.RS 0n
+message ExitMessage {
+ TimeSpec run_time = 1;
+ int32 exit_value = 2;
+ bool dumped_core = 3;
+ string signal = 4;
+ string error = 5;
+}
+.PP
+.RE
+.fi
+An
+\fIExitMessage\fR
+is sent by the client after the command has exited or has been
+terminated by a signal.
+It contains the following members:
+.TP 8n
+run_time
+The total amount of elapsed time since the command started,
+calculated using a monotonic clock where possible.
+This is not the wall clock time.
+.TP 8n
+exit_value
+The command's exit value in the range 0-255.
+.TP 8n
+dumped_core
+True if the command was terminated by a signal and dumped core.
+.TP 8n
+signal
+If the command was terminated by a signal, this is set to the
+name of the signal without the leading
+\(lqSIG\(rq.
+For example,
+\fRINT\fR,
+\fRTERM\fR,
+\fRKILL\fR,
+\fRSEGV\fR.
+.TP 8n
+error
+A message from the client indicating that the command was terminated
+unexpectedly due to an error.
+.PP
+When performing I/O logging, the client should wait for a
+\fIcommit_point\fR
+corresponding to the final
+\fIIoBuffer\fR
+before closing the connection unless the final
+\fIcommit_point\fR
+has already been received.
+.SS "RestartMessage restart_msg"
+.nf
+.RS 0n
+message RestartMessage {
+ string log_id = 1;
+ TimeSpec resume_point = 2;
+}
+.RE
+.fi
+.PP
+A
+\fIRestartMessage\fR
+is sent by the client to resume sending an existing I/O log that
+was previously interrupted.
+It contains the following members:
+.TP 8n
+log_id
+The the server-side name for an I/O log that was previously
+sent to the client by the server.
+This may be a path name on the server or some other kind of server-side
+identifier.
+.TP 8n
+resume_point
+The point in time after which to resume the I/O log.
+This is in the form of a
+\fITimeSpec\fR
+representing the amount of time since the command started, not
+the wall clock time.
+The
+\fIresume_point\fR
+should correspond to a
+\fIcommit_point\fR
+previously sent to the client by the server.
+If the server receives a
+\fIRestartMessage\fR
+containing a
+\fIresume_point\fR
+it has not previously seen, an error will be returned to the client
+and the connection will be dropped.
+.PP
+If a
+\fIRestartMessage\fR
+is sent, the client must not send an
+\fIAcceptMessage\fR
+or
+\fIRejectMessage\fR.
+.SS "AlertMessage alert_msg"
+.nf
+.RS 0n
+message AlertMessage {
+ TimeSpec alert_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.RE
+.fi
+.PP
+An
+\fIAlertMessage\fR
+is sent by the client to indicate a problem detected by the security
+policy while the command is running that should be stored in the event log.
+It contains the following members:
+.TP 8n
+alert_time
+The wall clock time when the alert occurred.
+.TP 8n
+reason
+The reason for the alert.
+.TP 8n
+info_msgs
+An optional array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.SS "IoBuffer ttyin_buf | ttyout_buf | stdin_buf | stdout_buf | stderr_buf"
+.nf
+.RS 0n
+message IoBuffer {
+ TimeSpec delay = 1;
+ bytes data = 2;
+}
+.RE
+.fi
+.PP
+An
+\fIIoBuffer\fR
+is used to represent data from terminal input, terminal
+output, standard input, standard output or standard error.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+data
+The binary I/O log data from terminal input, terminal output,
+standard input, standard output or standard error.
+.SS "ChangeWindowSize winsize_event"
+.nf
+.RS 0n
+message ChangeWindowSize {
+ TimeSpec delay = 1;
+ int32 rows = 2;
+ int32 cols = 3;
+}
+.RE
+.fi
+.PP
+A
+\fIChangeWindowSize\fR
+message is sent by the client when the terminal running the command
+changes size.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+rows
+The new number of terminal rows.
+.TP 8n
+cols
+The new number of terminal columns.
+.SS "CommandSuspend suspend_event"
+.nf
+.RS 0n
+message CommandSuspend {
+ TimeSpec delay = 1;
+ string signal = 2;
+}
+.RE
+.fi
+.PP
+A
+\fICommandSuspend\fR
+message is sent by the client when the command is either suspended
+or resumed.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+signal
+The signal name without the leading
+\(lqSIG\(rq.
+For example,
+\fRSTOP\fR,
+\fRTSTP\fR,
+\fRCONT\fR.
+.SH "Server Messages"
+A
+\fIServerMessage\fR
+is a container used to encapsulate all the possible message types
+the server may send to a client.
+.nf
+.sp
+.RS 0n
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1;
+ TimeSpec commit_point = 2;
+ string log_id = 3;
+ string error = 4;
+ string abort = 5;
+ }
+}
+.RE
+.fi
+.PP
+The different
+\fIServerMessage\fR
+sub-messages the server may sent to the client are described below.
+.SS "ServerHello hello"
+.nf
+.RS 0n
+message ServerHello {
+ string server_id = 1;
+ string redirect = 2;
+ repeated string servers = 3;
+}
+.RE
+.fi
+.PP
+The
+\fIServerHello\fR
+message consists of server information sent when the client first connects.
+It contains the following members:
+.TP 8n
+server_id
+A free-form server description.
+Usually this includes the name and version of the implementation
+running on the log server.
+This member is always present.
+.TP 8n
+redirect
+A host and port separated by a colon
+(\(oq\(cq):
+that the client should connect to instead.
+The host may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+This may be used for server load balancing.
+The server will disconnect after sending the
+\fIServerHello\fR
+when it includes a
+\fBredirect\fR.
+.TP 8n
+servers
+.br
+A list of other known log servers.
+This can be used to implement log server redundancy and allows the
+client to discover all other log servers simply by connecting to
+one known server.
+This member may be omitted when there is only a single log server.
+.SS "TimeSpec commit_point"
+A periodic time stamp sent by the server to indicate when I/O log
+buffers have been committed to storage.
+This message is not sent after every
+\fIIoBuffer\fR
+but rather at a server-configurable interval.
+When the server receives an
+\fIExitMessage\fR,
+it will respond with a
+\fIcommit_point\fR
+corresponding to the last received
+\fIIoBuffer\fR
+before closing the connection.
+.SS "string log_id"
+The server-side ID of the I/O log being stored, sent in response
+to an
+\fIAcceptMessage\fR
+where
+\fIexpect_iobufs\fR
+is true.
+.SS "string error"
+A fatal server-side error.
+The server will close the connection after sending the
+\fIerror\fR
+message.
+.SS "string abort"
+An
+\fIabort\fR
+message from the server indicates that the client should kill the
+command and terminate the session.
+It may be used to implement simple server-side policy.
+The server will close the connection after sending the
+\fIabort\fR
+message.
+.SH "Protocol flow of control"
+The expected protocol flow is as follows:
+.TP 5n
+1.\&
+Client connects to the first available server.
+If the client is configured to use TLS, a TLS handshake will be
+attempted.
+.TP 5n
+2.\&
+Client sends
+\fIClientHello\fR.
+This is currently optional but allows the server to detect a
+non-TLS connection on the TLS port.
+.TP 5n
+3.\&
+Server sends
+\fIServerHello\fR.
+.TP 5n
+4.\&
+Client responds with either
+\fIAcceptMessage\fR,
+\fIRejectMessage\fR,
+or
+\fIRestartMessage\fR.
+.TP 5n
+5.\&
+If client sent a
+\fIAcceptMessage\fR
+with
+\fIexpect_iobufs\fR
+set, server creates a new I/O log and responds with a
+\fIlog_id\fR.
+.TP 5n
+6.\&
+Client sends zero or more
+\fIIoBuffer\fR
+messages.
+.TP 5n
+7.\&
+Server periodically responds to
+\fIIoBuffer\fR
+messages with a
+\fIcommit_point\fR.
+.TP 5n
+8.\&
+Client sends an
+\fIExitMessage\fR
+when the command exits or is killed.
+.TP 5n
+9.\&
+Server sends the final
+\fIcommit_point\fR
+if one is pending.
+.TP 5n
+10.\&
+Server closes the connection.
+After receiving the final
+\fIcommit_point\fR,
+the client shuts down its side of the TLS connection if TLS
+is in use, and closes the connection.
+.TP 5n
+11.\&
+Server shuts down its side of the TLS connection if TLS is in use,
+and closes the connection.
+.PP
+At any point, the server may send an
+\fIerror\fR
+or
+\fIabort\fR
+message to the client at which point the server will close the
+connection.
+If an
+\fIabort\fR
+message is received, the client should terminate the running command.
+.SH "EVENT LOG VARIABLES"
+\fIAcceptMessage\fR,
+\fIAlertMessage\fR
+and
+\fIRejectMessage\fR
+classes contain an array of
+\fIInfoMessage\fR
+that should contain information about the user who submitted the command
+as well as information about the execution environment of the command
+if it was accepted.
+.PP
+Some variables have a
+\fIclient\fR,
+\fIrun\fR,
+or
+\fIsubmit\fR
+prefix.
+These prefixes are used to eliminate ambiguity for variables that
+could apply to the client program, the user submitting the command,
+or the command being run.
+Variables with a
+\fIclient\fR
+prefix pertain to the program performing the connection to the log
+server, for example
+\fBsudo\fR.
+Variables with a
+\fIrun\fR
+prefix pertain to the command that the user requested be run.
+Variables with a
+\fIsubmit\fR
+prefix pertain to the user submitting the request
+(the user running \fBsudo\fR).
+.PP
+The following
+\fIInfoMessage\fR
+entries are required:
+.TS
+l l l.
+.PP
+\fBKey\fR \fBType\fR \fBDescription\fR
+.PP
+command string command that was submitted
+.PP
+runuser string name of user the command was run as
+.PP
+submithost string name of host the command was submitted on
+.PP
+submituser string name of user submitting the command
+.TE
+.PP
+The following
+\fIInfoMessage\fR
+entries are recognized, but not required:
+.TS
+l l l.
+.PP
+\fBKey\fR \fBType\fR \fBDescription\fR
+.PP
+clientargv StringList client's original argument vector
+.PP
+clientpid int64 client's process ID
+.PP
+clientppid int64 client's parent process ID
+.PP
+clientsid int64 client's terminal session ID
+.PP
+columns int64 number of columns in the terminal
+.PP
+lines int64 number of lines in the terminal
+.PP
+runargv StringList argument vector of command to run
+.PP
+runchroot string root directory of command to run
+.PP
+runcwd string running command's working directory
+.PP
+runenv StringList the running command's environment
+.PP
+rungid int64 primary group-ID of the command
+.PP
+rungids NumberList supplementary group-IDs for the command
+.PP
+rungroup string primary group name of the command
+.PP
+rungroups StringList supplementary group names for the command
+.PP
+runuid int64 run user's user-ID
+.PP
+submitcwd string submit user's current working directory
+.PP
+submitenv StringList the submit user's environment
+.PP
+submitgid int64 submit user's primary group-ID
+.PP
+submitgids NumberList submit user's supplementary group-IDs
+.PP
+submitgroup string submitting user's primary group name
+.PP
+submitgroups StringList submit user's supplementary group names
+.PP
+submituid int64 submit user's user-ID
+.PP
+ttyname string the terminal the command was submitted from
+.TE
+.PP
+The server must accept other variables not listed above but may
+ignore them.
+.SH "EXAMPLES"
+The Protocol Buffers description of the log server protocol is included
+in full below.
+Note that this uses the newer
+\(lqproto3\(rq
+syntax.
+.nf
+.sp
+.RS 0n
+syntax = "proto3";
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ }
+}
+
+/* Equivalent of POSIX struct timespec */
+message TimeSpec {
+ int64 tv_sec = 1; /* seconds */
+ int32 tv_nsec = 2; /* nanoseconds */
+}
+
+/* I/O buffer with keystroke data */
+message IoBuffer {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ bytes data = 2; /* keystroke data */
+}
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+message AcceptMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ repeated InfoMessage info_msgs = 2; /* key,value event log data */
+ bool expect_iobufs = 3; /* true if I/O logging enabled */
+}
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+message RejectMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ string reason = 2; /* reason command was rejected */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Message sent by client when command exits. */
+/* Might revisit runtime and use end_time instead */
+message ExitMessage {
+ TimeSpec run_time = 1; /* total elapsed run time */
+ int32 exit_value = 2; /* 0-255 */
+ bool dumped_core = 3; /* true if command dumped core */
+ string signal = 4; /* signal name if killed by signal */
+ string error = 5; /* if killed due to other error */
+}
+
+/* Alert message, policy module-specific. */
+message AlertMessage {
+ TimeSpec alert_time = 1; /* time alert message occurred */
+ string reason = 2; /* policy alert error string */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Used to restart an existing I/O log on the server. */
+message RestartMessage {
+ string log_id = 1; /* ID of log being restarted */
+ TimeSpec resume_point = 2; /* resume point (elapsed time) */
+}
+
+/* Window size change event. */
+message ChangeWindowSize {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ int32 rows = 2; /* new number of rows */
+ int32 cols = 3; /* new number of columns */
+}
+
+/* Command suspend/resume event. */
+message CommandSuspend {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ string signal = 2; /* signal that caused suspend/resume */
+}
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1; /* server hello message */
+ TimeSpec commit_point = 2; /* cumulative time of records stored */
+ string log_id = 3; /* ID of server-side I/O log */
+ string error = 4; /* error message from server */
+ string abort = 5; /* abort message, kill command */
+ }
+}
+
+/* Hello message from server when client connects. */
+message ServerHello {
+ string server_id = 1; /* free-form server description */
+ string redirect = 2; /* optional redirect if busy */
+ repeated string servers = 3; /* optional list of known servers */
+}
+.RE
+.fi
+.SH "SEE ALSO"
+sudo_logsrvd.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(8),
+sudo_logsrvd(8)
+.PP
+\fIProtocol Buffers\fR,
+https://developers.google.com/protocol-buffers/.
+.SH "HISTORY"
+See the HISTORY file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrv.proto.mdoc.in b/doc/sudo_logsrv.proto.mdoc.in
new file mode 100644
index 0000000..ef9953a
--- /dev/null
+++ b/doc/sudo_logsrv.proto.mdoc.in
@@ -0,0 +1,817 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.Dd November 6, 2020
+.Dt SUDO_LOGSRV.PROTO @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrv.proto
+.Nd Sudo log server protocol
+.Sh DESCRIPTION
+Starting with version 1.9.0,
+.Nm sudo
+supports sending event and I/O logs to a log server.
+The protocol used is written in Google's Protocol Buffers domain
+specific language.
+The
+.Sx EXAMPLES
+section includes a complete description of the protocol in Protocol
+Buffers format.
+.Pp
+Because there is no way to determine message boundaries when using
+Protocol Buffers, the wire size of each message is sent immediately
+preceding the message itself as a 32-bit unsigned integer in network
+byte order.
+This is referred to as
+.Dq length-prefix framing
+and is how Google suggests handling the lack of message delimiters.
+.Pp
+The protocol is made up of two basic messages,
+.Em ClientMessage
+and
+.Em ServerMessage ,
+described below.
+The server must accept messages up to two megabytes in size.
+The server may return an error if the client tries to send a message
+larger than two megabytes.
+.Sh Client Messages
+A
+.Em ClientMessage
+is a container used to encapsulate all the possible message types
+a client may send to the server.
+.Bd -literal
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ ClientHello hello_msg = 13;
+ }
+}
+.Ed
+.Pp
+The different
+.Em ClientMessage
+sub-messages the client may sent to the server are described below.
+.Ss TimeSpec
+.Bd -literal
+message TimeSpec {
+ int64 tv_sec = 1;
+ int32 tv_nsec = 2;
+}
+.Ed
+.Pp
+A
+.Em TimeSpec
+is the equivalent of a POSIX
+.Li struct timespec ,
+containing seconds and nanoseconds members.
+The
+.Em tv_sec
+member is a 64-bit integer to support dates after the year 2038.
+.Ss InfoMessage
+.Bd -literal
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+.Ed
+.Pp
+An
+.Em InfoMessage
+is used to represent information about the invoking user as well as the
+execution environment the command runs in the form of key-value pairs.
+The key is always a string but the value may be a 64-bit integer,
+a string, an array of strings or an array of 64-bit integers.
+The event log data is composed of
+.Em InfoMessage
+entries.
+See the
+.Sx EVENT LOG VARIABLES
+section for more information.
+.Ss ClientHello hello_msg
+.Bd -literal
+message ClientHello {
+ string client_id = 1;
+}
+.Ed
+.Pp
+A
+.Em ClientHello
+message consists of client information that may be sent to the
+server when the client first connects.
+.Bl -tag -width Ds
+.It client_id
+A free-form client description.
+This usually includes the name and version of the client implementation.
+.El
+.Ss AcceptMessage accept_msg
+.Bd -literal
+message AcceptMessage {
+ TimeSpec submit_time = 1;
+ repeated InfoMessage info_msgs = 2;
+ bool expect_iobufs = 3;
+}
+.Ed
+.Pp
+An
+.Em AcceptMessage
+is sent by the client when a command is allowed by the security policy.
+It contains the following members:
+.Bl -tag -width Ds
+.It submit_time
+The wall clock time when the command was submitted to the security policy.
+.It info_msgs
+An array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry and may also be
+used by server to determine where and how the I/O log is stored.
+.It expect_iobufs
+Set to true if the server should expect
+.Em IoBuffer
+messages to follow (for I/O logging) or false if the server should only
+store the event log.
+.El
+.Pp
+If an
+.Em AcceptMessage
+is sent, the client must not send a
+.Em RejectMessage
+or
+.Em RestartMessage .
+.Ss RejectMessage reject_msg
+.Bd -literal
+message RejectMessage {
+ TimeSpec submit_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.Ed
+.Pp
+A
+.Em RejectMessage
+is sent by the client when a command is denied by the security policy.
+It contains the following members:
+.Bl -tag -width Ds
+.It submit_time
+The wall clock time when the command was submitted to the security policy.
+.It reason
+The reason the security policy gave for denying the command.
+.It info_msgs
+An array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.El
+.Pp
+If a
+.Em RejectMessage
+is sent, the client must not send an
+.Em AcceptMessage
+or
+.Em RestartMessage .
+.Ss ExitMessage exit_msg
+.Bd -literal
+message ExitMessage {
+ TimeSpec run_time = 1;
+ int32 exit_value = 2;
+ bool dumped_core = 3;
+ string signal = 4;
+ string error = 5;
+}
+.Pp
+.Ed
+An
+.Em ExitMessage
+is sent by the client after the command has exited or has been
+terminated by a signal.
+It contains the following members:
+.Bl -tag -width Ds
+.It run_time
+The total amount of elapsed time since the command started,
+calculated using a monotonic clock where possible.
+This is not the wall clock time.
+.It exit_value
+The command's exit value in the range 0-255.
+.It dumped_core
+True if the command was terminated by a signal and dumped core.
+.It signal
+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 .
+.It error
+A message from the client indicating that the command was terminated
+unexpectedly due to an error.
+.El
+.Pp
+When performing I/O logging, the client should wait for a
+.Em commit_point
+corresponding to the final
+.Em IoBuffer
+before closing the connection unless the final
+.Em commit_point
+has already been received.
+.Ss RestartMessage restart_msg
+.Bd -literal
+message RestartMessage {
+ string log_id = 1;
+ TimeSpec resume_point = 2;
+}
+.Ed
+.Pp
+A
+.Em RestartMessage
+is sent by the client to resume sending an existing I/O log that
+was previously interrupted.
+It contains the following members:
+.Bl -tag -width Ds
+.It log_id
+The the server-side name for an I/O log that was previously
+sent to the client by the server.
+This may be a path name on the server or some other kind of server-side
+identifier.
+.It resume_point
+The point in time after which to resume the I/O log.
+This is in the form of a
+.Em TimeSpec
+representing the amount of time since the command started, not
+the wall clock time.
+The
+.Em resume_point
+should correspond to a
+.Em commit_point
+previously sent to the client by the server.
+If the server receives a
+.Em RestartMessage
+containing a
+.Em resume_point
+it has not previously seen, an error will be returned to the client
+and the connection will be dropped.
+.El
+.Pp
+If a
+.Em RestartMessage
+is sent, the client must not send an
+.Em AcceptMessage
+or
+.Em RejectMessage .
+.Ss AlertMessage alert_msg
+.Bd -literal
+message AlertMessage {
+ TimeSpec alert_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.Ed
+.Pp
+An
+.Em AlertMessage
+is sent by the client to indicate a problem detected by the security
+policy while the command is running that should be stored in the event log.
+It contains the following members:
+.Bl -tag -width Ds
+.It alert_time
+The wall clock time when the alert occurred.
+.It reason
+The reason for the alert.
+.It info_msgs
+An optional array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.El
+.Ss IoBuffer ttyin_buf | ttyout_buf | stdin_buf | stdout_buf | stderr_buf
+.Bd -literal
+message IoBuffer {
+ TimeSpec delay = 1;
+ bytes data = 2;
+}
+.Ed
+.Pp
+An
+.Em IoBuffer
+is used to represent data from terminal input, terminal
+output, standard input, standard output or standard error.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It data
+The binary I/O log data from terminal input, terminal output,
+standard input, standard output or standard error.
+.El
+.Ss ChangeWindowSize winsize_event
+.Bd -literal
+message ChangeWindowSize {
+ TimeSpec delay = 1;
+ int32 rows = 2;
+ int32 cols = 3;
+}
+.Ed
+.Pp
+A
+.Em ChangeWindowSize
+message is sent by the client when the terminal running the command
+changes size.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It rows
+The new number of terminal rows.
+.It cols
+The new number of terminal columns.
+.El
+.Ss CommandSuspend suspend_event
+.Bd -literal
+message CommandSuspend {
+ TimeSpec delay = 1;
+ string signal = 2;
+}
+.Ed
+.Pp
+A
+.Em CommandSuspend
+message is sent by the client when the command is either suspended
+or resumed.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It signal
+The signal name without the leading
+.Dq SIG .
+For example,
+.Li STOP ,
+.Li TSTP ,
+.Li CONT .
+.El
+.Sh Server Messages
+A
+.Em ServerMessage
+is a container used to encapsulate all the possible message types
+the server may send to a client.
+.Bd -literal
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1;
+ TimeSpec commit_point = 2;
+ string log_id = 3;
+ string error = 4;
+ string abort = 5;
+ }
+}
+.Ed
+.Pp
+The different
+.Em ServerMessage
+sub-messages the server may sent to the client are described below.
+.Ss ServerHello hello
+.Bd -literal
+message ServerHello {
+ string server_id = 1;
+ string redirect = 2;
+ repeated string servers = 3;
+}
+.Ed
+.Pp
+The
+.Em ServerHello
+message consists of server information sent when the client first connects.
+It contains the following members:
+.Bl -tag -width Ds
+.It server_id
+A free-form server description.
+Usually this includes the name and version of the implementation
+running on the log server.
+This member is always present.
+.It redirect
+A host and port separated by a colon
+.Pq Ql :
+that the client should connect to instead.
+The host may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+This may be used for server load balancing.
+The server will disconnect after sending the
+.Em ServerHello
+when it includes a
+.Sy redirect .
+.It servers
+A list of other known log servers.
+This can be used to implement log server redundancy and allows the
+client to discover all other log servers simply by connecting to
+one known server.
+This member may be omitted when there is only a single log server.
+.El
+.Ss TimeSpec commit_point
+A periodic time stamp sent by the server to indicate when I/O log
+buffers have been committed to storage.
+This message is not sent after every
+.Em IoBuffer
+but rather at a server-configurable interval.
+When the server receives an
+.Em ExitMessage ,
+it will respond with a
+.Em commit_point
+corresponding to the last received
+.Em IoBuffer
+before closing the connection.
+.Ss string log_id
+The server-side ID of the I/O log being stored, sent in response
+to an
+.Em AcceptMessage
+where
+.Em expect_iobufs
+is true.
+.Ss string error
+A fatal server-side error.
+The server will close the connection after sending the
+.Em error
+message.
+.Ss string abort
+An
+.Em abort
+message from the server indicates that the client should kill the
+command and terminate the session.
+It may be used to implement simple server-side policy.
+The server will close the connection after sending the
+.Em abort
+message.
+.Sh Protocol flow of control
+The expected protocol flow is as follows:
+.Bl -enum
+.It
+Client connects to the first available server.
+If the client is configured to use TLS, a TLS handshake will be
+attempted.
+.It
+Client sends
+.Em ClientHello .
+This is currently optional but allows the server to detect a
+non-TLS connection on the TLS port.
+.It
+Server sends
+.Em ServerHello .
+.It
+Client responds with either
+.Em AcceptMessage ,
+.Em RejectMessage ,
+or
+.Em RestartMessage .
+.It
+If client sent a
+.Em AcceptMessage
+with
+.Em expect_iobufs
+set, server creates a new I/O log and responds with a
+.Em log_id .
+.It
+Client sends zero or more
+.Em IoBuffer
+messages.
+.It
+Server periodically responds to
+.Em IoBuffer
+messages with a
+.Em commit_point .
+.It
+Client sends an
+.Em ExitMessage
+when the command exits or is killed.
+.It
+Server sends the final
+.Em commit_point
+if one is pending.
+.It
+Server closes the connection.
+After receiving the final
+.Em commit_point ,
+the client shuts down its side of the TLS connection if TLS
+is in use, and closes the connection.
+.It
+Server shuts down its side of the TLS connection if TLS is in use,
+and closes the connection.
+.El
+.Pp
+At any point, the server may send an
+.Em error
+or
+.Em abort
+message to the client at which point the server will close the
+connection.
+If an
+.Em abort
+message is received, the client should terminate the running command.
+.Sh EVENT LOG VARIABLES
+.Em AcceptMessage ,
+.Em AlertMessage
+and
+.Em RejectMessage
+classes contain an array of
+.Em InfoMessage
+that should contain information about the user who submitted the command
+as well as information about the execution environment of the command
+if it was accepted.
+.Pp
+Some variables have a
+.Em client ,
+.Em run ,
+or
+.Em submit
+prefix.
+These prefixes are used to eliminate ambiguity for variables that
+could apply to the client program, the user submitting the command,
+or the command being run.
+Variables with a
+.Em client
+prefix pertain to the program performing the connection to the log
+server, for example
+.Nm sudo .
+Variables with a
+.Em run
+prefix pertain to the command that the user requested be run.
+Variables with a
+.Em submit
+prefix pertain to the user submitting the request
+.Pq the user running Nm sudo .
+.Pp
+The following
+.Em InfoMessage
+entries are required:
+.Bl -column "submitgroup" "stringlist" "name of host the command was submitted on"
+.It Sy Key Ta Sy Type Ta Sy Description
+.It command Ta string Ta command that was submitted
+.It runuser Ta string Ta name of user the command was run as
+.It submithost Ta string Ta name of host the command was submitted on
+.It submituser Ta string Ta name of user submitting the command
+.El
+.Pp
+The following
+.Em InfoMessage
+entries are recognized, but not required:
+.Bl -column "submitgroup" "stringlist" "name of host the command was submitted on"
+.It Sy Key Ta Sy Type Ta Sy Description
+.It clientargv Ta StringList Ta client's original argument vector
+.It clientpid Ta int64 Ta client's process ID
+.It clientppid Ta int64 Ta client's parent process ID
+.It clientsid Ta int64 Ta client's terminal session ID
+.It columns Ta int64 Ta number of columns in the terminal
+.It lines Ta int64 Ta number of lines in the terminal
+.It runargv Ta StringList Ta argument vector of command to run
+.It runchroot Ta string Ta root directory of command to run
+.It runcwd Ta string Ta running command's working directory
+.It runenv Ta StringList Ta the running command's environment
+.It rungid Ta int64 Ta primary group-ID of the command
+.It rungids Ta NumberList Ta supplementary group-IDs for the command
+.It rungroup Ta string Ta primary group name of the command
+.It rungroups Ta StringList Ta supplementary group names for the command
+.It runuid Ta int64 Ta run user's user-ID
+.It submitcwd Ta string Ta submit user's current working directory
+.It submitenv Ta StringList Ta the submit user's environment
+.It submitgid Ta int64 Ta submit user's primary group-ID
+.It submitgids Ta NumberList Ta submit user's supplementary group-IDs
+.It submitgroup Ta string Ta submitting user's primary group name
+.It submitgroups Ta StringList Ta submit user's supplementary group names
+.It submituid Ta int64 Ta submit user's user-ID
+.It ttyname Ta string Ta the terminal the command was submitted from
+.El
+.Pp
+The server must accept other variables not listed above but may
+ignore them.
+.Sh EXAMPLES
+The Protocol Buffers description of the log server protocol is included
+in full below.
+Note that this uses the newer
+.Dq proto3
+syntax.
+.Bd -literal
+syntax = "proto3";
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ }
+}
+
+/* Equivalent of POSIX struct timespec */
+message TimeSpec {
+ int64 tv_sec = 1; /* seconds */
+ int32 tv_nsec = 2; /* nanoseconds */
+}
+
+/* I/O buffer with keystroke data */
+message IoBuffer {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ bytes data = 2; /* keystroke data */
+}
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+message AcceptMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ repeated InfoMessage info_msgs = 2; /* key,value event log data */
+ bool expect_iobufs = 3; /* true if I/O logging enabled */
+}
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+message RejectMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ string reason = 2; /* reason command was rejected */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Message sent by client when command exits. */
+/* Might revisit runtime and use end_time instead */
+message ExitMessage {
+ TimeSpec run_time = 1; /* total elapsed run time */
+ int32 exit_value = 2; /* 0-255 */
+ bool dumped_core = 3; /* true if command dumped core */
+ string signal = 4; /* signal name if killed by signal */
+ string error = 5; /* if killed due to other error */
+}
+
+/* Alert message, policy module-specific. */
+message AlertMessage {
+ TimeSpec alert_time = 1; /* time alert message occurred */
+ string reason = 2; /* policy alert error string */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Used to restart an existing I/O log on the server. */
+message RestartMessage {
+ string log_id = 1; /* ID of log being restarted */
+ TimeSpec resume_point = 2; /* resume point (elapsed time) */
+}
+
+/* Window size change event. */
+message ChangeWindowSize {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ int32 rows = 2; /* new number of rows */
+ int32 cols = 3; /* new number of columns */
+}
+
+/* Command suspend/resume event. */
+message CommandSuspend {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ string signal = 2; /* signal that caused suspend/resume */
+}
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1; /* server hello message */
+ TimeSpec commit_point = 2; /* cumulative time of records stored */
+ string log_id = 3; /* ID of server-side I/O log */
+ string error = 4; /* error message from server */
+ string abort = 5; /* abort message, kill command */
+ }
+}
+
+/* Hello message from server when client connects. */
+message ServerHello {
+ string server_id = 1; /* free-form server description */
+ string redirect = 2; /* optional redirect if busy */
+ repeated string servers = 3; /* optional list of known servers */
+}
+.Ed
+.Sh SEE ALSO
+.Xr sudo_logsrvd.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Rs
+.%T Protocol Buffers
+.%U https://developers.google.com/protocol-buffers/
+.Re
+.Sh HISTORY
+See the HISTORY file in the
+.Nm sudo
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrvd.conf.man.in b/doc/sudo_logsrvd.conf.man.in
new file mode 100644
index 0000000..8c752e9
--- /dev/null
+++ b/doc/sudo_logsrvd.conf.man.in
@@ -0,0 +1,769 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "November 24, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrvd.conf\fR
+\- configuration for sudo_logsrvd
+.SH "DESCRIPTION"
+The
+\fBsudo_logsrvd.conf\fR
+file is used to configure the
+\fBsudo_logsrvd\fR
+log server.
+It uses an INI-style format made up of sections in square brackets and
+\(lqkey = value\(rq
+pairs specific to each section below the section name.
+Depending on the key, values may be integers, booleans or strings.
+Section and key names are not case sensitive, but values are.
+.PP
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+Lines beginning with a semi-colon
+(\(oq\&;\(cq)
+are also ignored.
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+Note that leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.PP
+The
+\fIEXAMPLES\fR
+section contains a copy of the default
+\fBsudo_logsrvd.conf\fR
+file.
+.PP
+The following configuration sections are recognized:
+.PP
+.RS 6n
+.PD 0
+.TP 4n
+\fB\(bu\fR
+server
+.TP 4n
+\fB\(bu\fR
+iolog
+.TP 4n
+\fB\(bu\fR
+eventlog
+.TP 4n
+\fB\(bu\fR
+syslog
+.TP 4n
+\fB\(bu\fR
+logfile
+.RE
+.PD
+.PP
+Each section is described in detail below.
+.SS "server"
+The
+\fIserver\fR
+section configures the address and port the server will listen on.
+The following keys are recognized:
+.TP 10n
+listen_address = host[:port][(tls)]
+The host name or IP address, optional port to listen on and
+an optional Transport Layer Security (TLS) flag in parentheses.
+.sp
+The host may be a host name, an IPv4 address, an IPv6 address
+in square brackets or the wild card entry
+\(oq*\(cq.
+A host setting of
+\(oq*\(cq
+will cause
+\fBsudo_logsrvd\fR
+to listen on all configured network interfaces.
+.sp
+If the optional tls flag is present,
+\fBsudo_logsrvd\fR
+will secure the connection with TLS version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+See
+sudo_logsrvd(8)
+for details on generating TLS keys and certificates.
+.sp
+If a port is specified, it may either be a port number or a known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.sp
+The default value is:
+.nf
+.RS 16n
+listen_address = *:30343
+listen_address = *:30344(tls)
+.RE
+.fi
+.RS 10n
+which will listen on all configured network interfaces for both
+plaintext and TLS connections.
+Multiple
+\fIlisten_address\fR
+lines may be specified to listen on more than one port or interface.
+.RE
+.TP 10n
+pid_file = path
+The path to the file containing the process ID of the running
+\fBsudo_logsrvd\fR.
+If set to an empty value, or if
+\fBsudo_logsrvd\fR
+is run with the
+\fB\-n\fR
+option, no
+\fIpid_file\fR
+will be created.
+If
+\fIpid_file\fR
+refers to a symbolic link, it will be ignored.
+The default value is
+\fI@rundir@/sudo_logsrvd.pid\fR.
+.TP 10n
+tcp_keepalive = boolean
+If true,
+\fBsudo_logsrvd\fR
+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, the connection will be closed.
+.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.
+.TP 10n
+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
+when authenticating clients.
+The default is to use
+\fI/etc/ssl/sudo/cacert.pem\fR
+if it exists, otherwise the system's default certificate authority
+database is used.
+.TP 10n
+tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default value is
+\fI/etc/ssl/sudo/certs/logsrvd_cert.pem\fR.
+.TP 10n
+tls_checkpeer = bool
+If true, client certificates will be validated by the server;
+clients without a valid certificate will be unable to connect.
+If false, no validation of client certificates will be performed.
+It true and client certificates are created using a private certificate
+authority, the
+\fItls_cacert\fR
+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.
+.TP 10n
+tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+\(oq:\&\(cq.
+See the
+\fICIPHER LIST FORMAT\fR
+section in
+openssl-ciphers(1)
+for full details.
+The default value is
+\fRHIGH:!aNULL\fR
+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.
+.TP 10n
+tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+\(oq:\&\(cq.
+Supported cipher suites depend on the version of OpenSSL used,
+but should include the following:
+.sp
+.RS 16n
+.PD 0
+.TP 10n
+TLS_AES_128_GCM_SHA256
+.TP 10n
+TLS_AES_256_GCM_SHA384
+.TP 10n
+TLS_CHACHA20_POLY1305_SHA256
+.TP 10n
+TLS_AES_128_CCM_SHA256
+.TP 10n
+TLS_AES_128_CCM_8_SHA256
+.RE
+.RS 10n
+.sp
+The default cipher suite is TLS_AES_256_GCM_SHA384.
+.RE
+.PD
+.TP 10n
+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:
+.nf
+.sp
+.RS 10n
+openssl dhparam -out /etc/sudo_logsrvd_dhparams.pem 2048
+.RE
+.fi
+.RS 10n
+.sp
+By default,
+\fBsudo_logsrvd\fR
+will use the OpenSSL defaults for Diffie-Hellman key generation.
+.RE
+.TP 10n
+tls_key = path
+The path to the server's private key file, in PEM format.
+The default value is
+\fI/etc/ssl/sudo/private/logsrvd_key.pem\fR.
+.TP 10n
+tls_verify = bool
+If true, the server certificate will be verified at startup and
+clients will authenticate the server by verifying its certificate
+and identity.
+If false, no verification is performed of the server certificate
+by the server or the client.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default value is true.
+.SS "iolog"
+The
+\fIiolog\fR
+section configures I/O log parameters.
+These settings are identical to the I/O configuration in
+sudoers(@mansectform@).
+The following keys are recognized:
+.TP 10n
+iolog_compress = boolean
+If set, I/O logs will be compressed using
+\fBzlib\fR.
+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.
+.TP 10n
+iolog_dir = path
+The top-level directory to use when constructing the path
+name for the I/O log directory.
+The session sequence number, if any, is stored in the directory.
+The default value is
+\fI@iolog_dir@\fR.
+.sp
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 10n
+.PD 0
+.TP 6n
+\fR%{seq}\fR
+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
+expanded to the invoking user's login name
+.TP 6n
+\fR%{group}\fR
+expanded to the name of the invoking user's real group-ID
+.TP 6n
+\fR%{runas_user}\fR
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.TP 6n
+\fR%{runas_group}\fR
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.TP 6n
+\fR%{hostname}\fR
+expanded to the local host name without the domain name
+.TP 6n
+\fR%{command}\fR
+expanded to the base name of the command being run
+.PP
+In addition, any escape sequences supported by the system's
+strftime(3)
+function will be expanded.
+.sp
+To include a literal
+\(oq%\(cq
+character, the string
+\(oq%%\(cq
+should be used.
+.RE
+.TP 10n
+iolog_file = path
+The path name, relative to
+\fIiolog_dir\fR,
+in which to store I/O logs.
+Note that
+\fIiolog_file\fR
+may contain directory components.
+The default value is
+\fR%{seq}\fR.
+.sp
+See the
+\fIiolog_dir\fR
+setting above for a list of supported percent
+(\(oq%\(cq)
+escape sequences.
+.sp
+In addition to the escape sequences, path names that end in six or
+more
+\fRX\fRs
+will have the
+\fRX\fRs
+replaced with a unique combination of digits and letters, similar to the
+mktemp(3)
+function.
+.sp
+If the path created by concatenating
+\fIiolog_dir\fR
+and
+\fIiolog_file\fR
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+\fIiolog_file\fR
+ends in six or
+more
+\fRX\fRs.
+.TP 10n
+iolog_flush = boolean
+If set, I/O log data is flushed to disk after each write instead of
+buffering it.
+This makes it possible to view the logs in real-time as the program is
+executing but may significantly reduce the effectiveness
+of I/O log compression.
+The default value is
+\fRtrue\fR.
+.TP 10n
+iolog_group = name
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+\fIiolog_group\fR
+is not set,
+the primary group-ID of the user specified by
+\fIiolog_user is used.\fR
+If neither
+\fIiolog_group\fR
+nor
+\fIiolog_user\fR
+are set, I/O log files and directories are created with group-ID 0.
+.TP 10n
+iolog_mode = mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+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.
+.TP 10n
+iolog_user = name
+The user name to look up when setting the owner of new
+I/O log files and directories.
+If
+\fIiolog_group\fR
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.TP 10n
+maxseq = number
+The maximum sequence number that will be substituted for the
+\(lq\fR%{seq}\fR\(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
+is in base 36,
+\fImaxseq\fR
+itself should be expressed in decimal.
+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.
+.SS "eventlog"
+The
+\fIeventlog\fR
+section configures how (and if) security policy events are logged.
+.TP 6n
+log_type = string
+Where to log accept, reject and alert events reported by the policy.
+Supported values are
+\fIsyslog\fR,
+\fIlogfile\fR,
+and
+\fInone\fR.
+The default value is
+\fIsyslog\fR.
+.TP 6n
+log_format = string
+The event log format.
+Supported log formats are
+\(lqsudo\(rq
+for traditional sudo-style logs and
+\(lqjson\(rq
+for JSON-format logs.
+The JSON log entries contain the full contents of the accept, reject
+and alert messages.
+The default value is
+\fIsudo\fR.
+.SS "syslog"
+The
+\fIsyslog\fR
+section configures how events are logged via
+syslog(3).
+.TP 6n
+facility = string
+Syslog facility if syslog is being used for logging.
+Defaults to
+\fR@logfac@\fR.
+.sp
+The following syslog facilities are supported:
+\fBauthpriv\fR
+(if your
+OS supports it),
+\fBauth\fR,
+\fBdaemon\fR,
+\fBuser\fR,
+\fBlocal0\fR,
+\fBlocal1\fR,
+\fBlocal2\fR,
+\fBlocal3\fR,
+\fBlocal4\fR,
+\fBlocal5\fR,
+\fBlocal6\fR,
+and
+\fBlocal7\fR.
+.TP 6n
+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.
+.sp
+The following syslog priorities are supported:
+\fBalert\fR,
+\fBcrit\fR,
+\fBdebug\fR,
+\fBemerg\fR,
+\fBerr\fR,
+\fBinfo\fR,
+\fBnotice\fR,
+\fBwarning\fR,
+and
+\fBnone\fR.
+Setting it to a value of
+\fBnone\fR
+will disable logging of successful commands.
+.TP 6n
+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.
+.sp
+See
+\fIaccept_priority\fR
+for the list of supported syslog priorities.
+.TP 6n
+alert_priority = string
+Syslog priority to use for event log alert messages received from the client.
+Defaults to
+\fR@badpri@\fR.
+.sp
+See
+\fIaccept_priority\fR
+for the list of supported syslog priorities.
+.TP 6n
+maxlen = number
+On many systems,
+syslog(3)
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+\fBsudo_logsrvd\fR
+creates log messages up to 960 bytes which corresponds to the
+historic
+BSD
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname and program name.
+.sp
+To prevent syslog messages from being truncated,
+\fBsudo_logsrvd\fR
+will split up sudo-style log messages that are larger than
+\fImaxlen\fR
+bytes.
+When a message is split, additional parts will include the string
+\(lq(command continued)\(rq
+after the user name and before the continued command line arguments.
+JSON-format log entries are never split and are not affected by
+\fImaxlen\fR.
+.SS "logfile"
+The
+\fIlogfile\fR
+section consists of settings related to logging to a plain file
+(not syslog).
+.TP 6n
+path = string
+The path to the file-based event log.
+This path must be fully-qualified and start with a
+\(oq/\(cq
+character.
+The default value is
+\fI@logpath@\fR.
+.TP 6n
+time_format = string
+The string used when formatting the date and time for file-based event logs.
+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
+which produces dates like
+\(lqOct 3 07:15:24\(rq
+in the C locale.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo_logsrvd.conf\fR
+Sudo log server configuration file
+.SH "EXAMPLES"
+.nf
+.RS 0n
+#
+# sudo logsrv configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = @rundir@/sudo_logsrvd.pid
+
+# If set, enable the SO_KEEPALIVE socket option on the connected socket.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If set, server certificate will be verified at server startup and
+# also connecting clients will perform server authentication by
+# verifying the server's certificate and identity.
+#tls_verify = true
+
+# Whether to verify client certificates for TLS connections.
+# By default client certs are not checked.
+#tls_checkpeer = false
+
+# Path to the certificate authority bundle file in PEM format.
+# Required if 'tls_verify' or 'tls_checkpeer' is set.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+[eventlog]
+# Where to log accept, reject and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Event log format.
+# Currently only sudo-style event logs are supported.
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = alert
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
+.RE
+.fi
+.SH "SEE ALSO"
+strftime(3),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(8),
+sudo_logsrvd(8)
+.SH "HISTORY"
+See the HISTORY file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrvd.conf.mdoc.in b/doc/sudo_logsrvd.conf.mdoc.in
new file mode 100644
index 0000000..f3e883a
--- /dev/null
+++ b/doc/sudo_logsrvd.conf.mdoc.in
@@ -0,0 +1,712 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.Dd November 24, 2020
+.Dt SUDO_LOGSRVD.CONF @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrvd.conf
+.Nd configuration for sudo_logsrvd
+.Sh DESCRIPTION
+The
+.Nm sudo_logsrvd.conf
+file is used to configure the
+.Nm sudo_logsrvd
+log server.
+It uses an INI-style format made up of sections in square brackets and
+.Dq key = value
+pairs specific to each section below the section name.
+Depending on the key, values may be integers, booleans or strings.
+Section and key names are not case sensitive, but values are.
+.Pp
+The pound sign
+.Pq Ql #
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+Lines beginning with a semi-colon
+.Pq Ql \&;
+are also ignored.
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+Note that leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.Pp
+The
+.Sx EXAMPLES
+section contains a copy of the default
+.Nm
+file.
+.Pp
+The following configuration sections are recognized:
+.Pp
+.Bl -bullet -compact -offset indent
+.It
+server
+.It
+iolog
+.It
+eventlog
+.It
+syslog
+.It
+logfile
+.El
+.Pp
+Each section is described in detail below.
+.Ss server
+The
+.Em server
+section configures the address and port the server will listen on.
+The following keys are recognized:
+.Bl -tag -width 8n
+.It listen_address = host Ns Oo : Ns port Oc Ns Op (tls)
+The host name or IP address, optional port to listen on and
+an optional Transport Layer Security (TLS) flag in parentheses.
+.Pp
+The host may be a host name, an IPv4 address, an IPv6 address
+in square brackets or the wild card entry
+.Ql * .
+A host setting of
+.Ql *
+will cause
+.Nm sudo_logsrvd
+to listen on all configured network interfaces.
+.Pp
+If the optional tls flag is present,
+.Nm sudo_logsrvd
+will secure the connection with TLS version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+See
+.Xr sudo_logsrvd @mansectsu@
+for details on generating TLS keys and certificates.
+.Pp
+If a port is specified, it may either be a port number or a known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.Pp
+The default value is:
+.Bd -literal -compact -offset indent
+listen_address = *:30343
+listen_address = *:30344(tls)
+.Ed
+which will listen on all configured network interfaces for both
+plaintext and TLS connections.
+Multiple
+.Em listen_address
+lines may be specified to listen on more than one port or interface.
+.It pid_file = path
+The path to the file containing the process ID of the running
+.Nm sudo_logsrvd .
+If set to an empty value, or if
+.Nm sudo_logsrvd
+is run with the
+.Fl n
+option, no
+.Em pid_file
+will be created.
+If
+.Em pid_file
+refers to a symbolic link, it will be ignored.
+The default value is
+.Pa @rundir@/sudo_logsrvd.pid .
+.It tcp_keepalive = boolean
+If true,
+.Nm sudo_logsrvd
+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, the connection will be closed.
+.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.
+.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
+when authenticating clients.
+The default is to use
+.Pa /etc/ssl/sudo/cacert.pem
+if it exists, otherwise the system's default certificate authority
+database is used.
+.It tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default value is
+.Pa /etc/ssl/sudo/certs/logsrvd_cert.pem .
+.It tls_checkpeer = bool
+If true, client certificates will be validated by the server;
+clients without a valid certificate will be unable to connect.
+If false, no validation of client certificates will be performed.
+It true and client certificates are created using a private certificate
+authority, the
+.Em tls_cacert
+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 .
+.It tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+.Ql :\& .
+See the
+.Sx CIPHER LIST FORMAT
+section in
+.Xr openssl-ciphers 1
+for full details.
+The default value is
+.Li 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.
+.It tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+.Ql :\& .
+Supported cipher suites depend on the version of OpenSSL used,
+but should include the following:
+.Pp
+.Bl -tag -compact -width 8n -offset indent
+.It TLS_AES_128_GCM_SHA256
+.It TLS_AES_256_GCM_SHA384
+.It TLS_CHACHA20_POLY1305_SHA256
+.It TLS_AES_128_CCM_SHA256
+.It TLS_AES_128_CCM_8_SHA256
+.El
+.Pp
+The default cipher suite is 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:
+.Bd -literal
+openssl dhparam -out /etc/sudo_logsrvd_dhparams.pem 2048
+.Ed
+.Pp
+By default,
+.Nm sudo_logsrvd
+will use the OpenSSL defaults for Diffie-Hellman key generation.
+.It tls_key = path
+The path to the server's private key file, in PEM format.
+The default value is
+.Pa /etc/ssl/sudo/private/logsrvd_key.pem .
+.It tls_verify = bool
+If true, the server certificate will be verified at startup and
+clients will authenticate the server by verifying its certificate
+and identity.
+If false, no verification is performed of the server certificate
+by the server or the client.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default value is true.
+.El
+.Ss iolog
+The
+.Em iolog
+section configures I/O log parameters.
+These settings are identical to the I/O configuration in
+.Xr sudoers @mansectform@ .
+The following keys are recognized:
+.Bl -tag -width 8n
+.It iolog_compress = boolean
+If set, I/O logs will be compressed using
+.Sy zlib .
+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 .
+.It iolog_dir = path
+The top-level directory to use when constructing the path
+name for the I/O log directory.
+The session sequence number, if any, is stored in the directory.
+The default value is
+.Pa @iolog_dir@ .
+.Pp
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It Li %{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}
+expanded to the invoking user's login name
+.It Li %{group}
+expanded to the name of the invoking user's real group-ID
+.It Li %{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.It Li %{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.It Li %{hostname}
+expanded to the local host name without the domain name
+.It Li %{command}
+expanded to the base name of the command being run
+.El
+.Pp
+In addition, any escape sequences supported by the system's
+.Xr strftime 3
+function will be expanded.
+.Pp
+To include a literal
+.Ql %
+character, the string
+.Ql %%
+should be used.
+.It iolog_file = path
+The path name, relative to
+.Em iolog_dir ,
+in which to store I/O logs.
+Note that
+.Em iolog_file
+may contain directory components.
+The default value is
+.Li %{seq} .
+.Pp
+See the
+.Em iolog_dir
+setting above for a list of supported percent
+.Pq Ql %
+escape sequences.
+.Pp
+In addition to the escape sequences, path names that end in six or
+more
+.Li X Ns s
+will have the
+.Li X Ns s
+replaced with a unique combination of digits and letters, similar to the
+.Xr mktemp 3
+function.
+.Pp
+If the path created by concatenating
+.Em iolog_dir
+and
+.Em iolog_file
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+.Em iolog_file
+ends in six or
+more
+.Li X Ns s .
+.It iolog_flush = boolean
+If set, I/O log data is flushed to disk after each write instead of
+buffering it.
+This makes it possible to view the logs in real-time as the program is
+executing but may significantly reduce the effectiveness
+of I/O log compression.
+The default value is
+.Li true .
+.It iolog_group = name
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+.Em iolog_group
+is not set,
+the primary group-ID of the user specified by
+.Em iolog_user is used.
+If neither
+.Em iolog_group
+nor
+.Em iolog_user
+are set, I/O log files and directories are created with group-ID 0.
+.It iolog_mode = mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+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 .
+.It iolog_user = name
+The user name to look up when setting the owner of new
+I/O log files and directories.
+If
+.Em iolog_group
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.It maxseq = number
+The maximum sequence number that will be substituted for the
+.Dq Li %{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}
+is in base 36,
+.Em maxseq
+itself should be expressed in decimal.
+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.
+.El
+.Ss eventlog
+The
+.Em eventlog
+section configures how (and if) security policy events are logged.
+.Bl -tag -width 4n
+.It log_type = string
+Where to log accept, reject and alert events reported by the policy.
+Supported values are
+.Em syslog ,
+.Em logfile ,
+and
+.Em none .
+The default value is
+.Em syslog .
+.It log_format = string
+The event log format.
+Supported log formats are
+.Dq sudo
+for traditional sudo-style logs and
+.Dq json
+for JSON-format logs.
+The JSON log entries contain the full contents of the accept, reject
+and alert messages.
+The default value is
+.Em sudo .
+.El
+.Ss syslog
+The
+.Em syslog
+section configures how events are logged via
+.Xr syslog 3 .
+.Bl -tag -width 4n
+.It facility = string
+Syslog facility if syslog is being used for logging.
+Defaults to
+.Li @logfac@ .
+.Pp
+The following syslog facilities are supported:
+.Sy authpriv
+(if your
+OS supports it),
+.Sy auth ,
+.Sy daemon ,
+.Sy user ,
+.Sy local0 ,
+.Sy local1 ,
+.Sy local2 ,
+.Sy local3 ,
+.Sy local4 ,
+.Sy local5 ,
+.Sy local6 ,
+and
+.Sy local7 .
+.It accept_priority = string
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to
+.Li @goodpri@ .
+.Pp
+The following syslog priorities are supported:
+.Sy alert ,
+.Sy crit ,
+.Sy debug ,
+.Sy emerg ,
+.Sy err ,
+.Sy info ,
+.Sy notice ,
+.Sy warning ,
+and
+.Sy none .
+Setting it to a value of
+.Sy none
+will disable logging of successful commands.
+.It reject_priority = string
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to
+.Li @badpri@ .
+.Pp
+See
+.Em accept_priority
+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@ .
+.Pp
+See
+.Em accept_priority
+for the list of supported syslog priorities.
+.It maxlen = number
+On many systems,
+.Xr syslog 3
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+.Nm sudo_logsrvd
+creates log messages up to 960 bytes which corresponds to the
+historic
+.Bx
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname and program name.
+.Pp
+To prevent syslog messages from being truncated,
+.Nm sudo_logsrvd
+will split up sudo-style log messages that are larger than
+.Em maxlen
+bytes.
+When a message is split, additional parts will include the string
+.Dq Pq command continued
+after the user name and before the continued command line arguments.
+JSON-format log entries are never split and are not affected by
+.Em maxlen .
+.El
+.Ss logfile
+The
+.Em logfile
+section consists of settings related to logging to a plain file
+(not syslog).
+.Bl -tag -width 4n
+.It path = string
+The path to the file-based event log.
+This path must be fully-qualified and start with a
+.Sq /
+character.
+The default value is
+.Pa @logpath@ .
+.It time_format = string
+The string used when formatting the date and time for file-based event logs.
+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"
+which produces dates like
+.Dq Oct 3 07:15:24
+in the C locale.
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo_logsrvd.conf
+Sudo log server configuration file
+.El
+.Sh EXAMPLES
+.Bd -literal
+#
+# sudo logsrv configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = @rundir@/sudo_logsrvd.pid
+
+# If set, enable the SO_KEEPALIVE socket option on the connected socket.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If set, server certificate will be verified at server startup and
+# also connecting clients will perform server authentication by
+# verifying the server's certificate and identity.
+#tls_verify = true
+
+# Whether to verify client certificates for TLS connections.
+# By default client certs are not checked.
+#tls_checkpeer = false
+
+# Path to the certificate authority bundle file in PEM format.
+# Required if 'tls_verify' or 'tls_checkpeer' is set.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+[eventlog]
+# Where to log accept, reject and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Event log format.
+# Currently only sudo-style event logs are supported.
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = alert
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
+.Ed
+.Sh SEE ALSO
+.Xr strftime 3 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Sh HISTORY
+See the HISTORY file in the
+.Nm sudo
+distribution (https://www.sudo.ws/history.html) for a brief
+history of sudo.
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrvd.man.in b/doc/sudo_logsrvd.man.in
new file mode 100644
index 0000000..2eae8d2
--- /dev/null
+++ b/doc/sudo_logsrvd.man.in
@@ -0,0 +1,438 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.TH "SUDO_LOGSRVD" "@mansectsu@" "March 28, 2020" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrvd\fR
+\- sudo event and I/O log server
+.SH "SYNOPSIS"
+.HP 13n
+\fBsudo_logsrvd\fR
+[\fB\-hnV\fR]
+[\fB\-f\fR\ \fIfile\fR]
+[\fB\-R\fR\ \fIpercentage\fR]
+.SH "DESCRIPTION"
+\fBsudo_logsrvd\fR
+is a high-performance log server that accepts event and I/O logs from
+\fBsudo\fR.
+It can be used to implement centralized logging of
+\fBsudo\fR
+logs.
+Event log entries may be logged either via
+syslog(3)
+or to a file.
+I/O Logs created by
+\fBsudo_logsrvd\fR
+can be replayed via the
+sudoreplay(@mansectsu@)
+utility in the same way as logs generated directly by the
+\fBsudoers\fR
+plugin.
+.PP
+The server also supports restarting interrupted log transfers.
+To distinguish completed I/O logs from incomplete ones, the
+I/O log timing file is set to be read-only when the log is complete.
+.PP
+Configuration parameters for
+\fBsudo_logsrvd\fR
+may be specified in the
+sudo_logsrvd.conf(@mansectform@)
+file.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-f\fR, \fB\--file\fR
+Read configuration from
+\fIfile\fR
+instead of the default,
+\fI@sysconfdir@/sudo_logsrvd.conf\fR.
+.TP 12n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-n\fR, \fB\--no-fork\fR
+Run
+\fBsudo_logsrvd\fR
+in the foreground instead of detaching from the terminal and becoming
+a daemon.
+.TP 12n
+\fB\-R\fR, \fB\--random-drop\fR
+For each message, there is a
+\fIpercentage\fR
+chance that the server will drop the connection.
+This is only intended for debugging the ability of a
+client to restart a connection.
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo_logsrvd\fR
+version and exit.
+.SS "Securing server connections"
+The I/O log data sent to
+\fBsudo_logsrvd\fR
+may contain sensitive information such as passwords and should be
+secured using Transport Layer Security (TLS).
+Doing so requires having a signed certificate on the server and, if
+\fItls_checkpeer\fR
+is enabled in
+sudo_logsrvd.conf(@mansectform@),
+a signed certificate on the client as well.
+.PP
+The certificates can either be signed by a well-known Certificate
+Authority (CA), or a private CA can be used.
+Instructions for creating a private CA are included below in the
+\fIEXAMPLES\fR
+section.
+.SS "Debugging sudo_logsrvd"
+\fBsudo_logsrvd\fR
+supports a flexible debugging framework that is configured via
+\fRDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+please refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front end configuration
+.TP 26n
+\fI@sysconfdir@/sudo_logsrvd.conf\fR
+Sudo log server configuration file
+.TP 26n
+\fI@iolog_dir@\fR
+Default I/O log file location
+.TP 26n
+\fI@rundir@/sudo_logsrvd.pid\fR
+.br
+Process ID file for
+\fBsudo_logsrvd\fR
+.SH "EXAMPLES"
+.SS "Creating self-signed certificates"
+Unless you are using certificates signed by a well-known Certificate
+Authority (or a local enterprise CA), you will need to create your
+own CA that can sign the certificates used by
+\fBsudo_logsrvd\fR,
+\fBsudo_sendlog\fR,
+and the
+\fBsudoers\fR
+plugin.
+The following steps use the
+openssl(1)
+command to create keys and certificates.
+.SS "Initial setup"
+First, we need to create a directory structure to store the
+files for the CA.
+We'll create a new directory hierarchy in
+\fI/etc/ssl/sudo\fR
+for this purpose.
+.nf
+.sp
+.RS 6n
+# mkdir /etc/ssl/sudo
+# cd /etc/ssl/sudo
+# mkdir certs csr newcerts private
+# chmod 700 private
+# touch index.txt
+# echo 1000 > serial
+.RE
+.fi
+.PP
+The serial and index.txt files are used to keep track of signed certificates.
+.PP
+Next, we need to make a copy of the openssl.conf file and customize
+it for our new CA.
+The path to openssl.cnf is system-dependent but
+\fI/etc/ssl/openssl.cnf\fR
+is the most common location.
+You will need to adjust the example below if it has a different location on
+your system.
+.nf
+.sp
+.RS 6n
+# cp /etc/ssl/openssl.cnf .
+.RE
+.fi
+.PP
+Now edit the
+\fIopenssl.cnf\fR
+file in the current directory and make sure it contains
+\(lqca\(rq
+and
+\(lqCA_default\(rq
+sections.
+Those sections should include the following settings:
+.nf
+.sp
+.RS 6n
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = /etc/ssl/sudo
+certs = $dir/certs
+database = $dir/index.txt
+certificate = $dir/cacert.pem
+serial = $dir/serial
+.RE
+.fi
+.PP
+If your
+\fIopenssl.conf\fR
+file already has a
+\(lqCA_default\(rq
+section, you may only need to modify the
+\(lqdir\(rq
+setting.
+.SS "Creating the CA key and certificate"
+In order to create and sign our own certificates, we need to create
+a private key and a certificate for the root of the CA.
+First, create the private key and protect it with a pass phrase:
+.nf
+.sp
+.RS 6n
+# openssl genrsa -aes256 -out private/cakey.pem 4096
+# chmod 400 private/cakey.pem
+.RE
+.fi
+.PP
+Next, generate the root certificate, using appropriate values for
+the site-specific fields:
+.nf
+.sp
+.RS 6n
+# openssl req -config openssl.cnf -key private/cakey.pem \e
+ -new -x509 -days 7300 -sha256 -extensions v3_ca \e
+ -out cacert.pem
+
+Enter pass phrase for private/cakey.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo Certificate Authority
+Common Name (e.g., server FQDN or YOUR name) []:sudo Root CA
+Email Address []:
+
+# chmod 444 cacert.pem
+.RE
+.fi
+.PP
+Finally, verify the root certificate:
+.nf
+.sp
+.RS 6n
+# openssl x509 -noout -text -in cacert.pem
+.RE
+.fi
+.SS "Creating and signing certificates"
+The server and client certificates will be signed by the previously
+created root CA.
+Usually, the root CA is not used to sign server/client certificates
+directly.
+Instead, intermediate certificates are created and signed with the
+root CA and the intermediate certs are used to sign CSRs (Certificate
+Signing Request).
+In this example we'll skip this part for simplicity's sake and sign the
+CSRs with the root CA.
+.PP
+First, generate the private key without a pass phrase.
+.nf
+.sp
+.RS 6n
+# openssl genrsa -out private/logsrvd_key.pem 2048
+# chmod 400 private/logsrvd_key.pem
+.RE
+.fi
+.PP
+Next, create a certificate signing request (CSR) for the server's certificate.
+The organization name must match the name given in the root certificate.
+The common name should be either the server's IP address or a fully
+qualified domain name.
+.nf
+.sp
+.RS 6n
+# openssl req -config openssl.cnf -key private/logsrvd_key.pem -new \e
+ -sha256 -out csr/logsrvd_csr.pem
+
+Enter pass phrase for private/logsrvd_key.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo log server
+Common Name (e.g., server FQDN or YOUR name) []:logserver.example.com
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+.RE
+.fi
+.PP
+Now sign the CSR that was just created:
+.nf
+.sp
+.RS 6n
+# openssl ca -config openssl.cnf -days 375 -notext -md sha256 \e
+ -in csr/logsrvd_csr.pem -out certs/logsrvd_cert.pem
+
+Using configuration from openssl.cnf
+Enter pass phrase for ./private/cakey.pem:
+Check that the request matches the signature
+Signature ok
+Certificate Details:
+ Serial Number: 4096 (0x1000)
+ Validity
+ Not Before: Nov 11 14:05:05 2019 GMT
+ Not After : Nov 20 14:05:05 2020 GMT
+ Subject:
+ countryName = US
+ stateOrProvinceName = Colorado
+ organizationName = sudo
+ organizationalUnitName = sudo log server
+ commonName = logserve.example.com
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 4C:50:F9:D0:BE:1A:4C:B2:AC:90:76:56:C7:9E:16:AE:E6:9E:E5:B5
+ X509v3 Authority Key Identifier:
+ keyid:D7:91:24:16:B1:03:06:65:1A:7A:6E:CF:51:E9:5C:CB:7A:95:3E:0C
+
+Certificate is to be certified until Nov 20 14:05:05 2020 GMT (375 days)
+Sign the certificate? [y/n]:y
+
+1 out of 1 certificate requests certified, commit? [y/n]y
+Write out database with 1 new entries
+Data Base Updated
+.RE
+.fi
+.PP
+Finally, verify the new certificate:
+.nf
+.sp
+.RS 6n
+# openssl verify -CAfile cacert.pem certs/logsrvd_cert.pem
+certs/logsrvd_cert.pem: OK
+.RE
+.fi
+.PP
+The
+\fI/etc/ssl/sudo/certs\fR
+directory now contains a signed and verified certificate for use with
+\fBsudo_logsrvd\fR.
+.PP
+To generate a client certificate, repeat the process above using
+a different file name.
+.SS "Configuring sudo_logsrvd to use TLS"
+To use TLS for client/server communication, both
+\fBsudo_logsrvd\fR
+and the
+\fBsudoers\fR
+plugin need to be configured to use TLS.
+Configuring
+\fBsudo_logsrvd\fR
+for TLS requires the following settings, assuming the same path
+names used earlier:
+.nf
+.sp
+.RS 6n
+# If set, secure connections with TLS 1.2 or 1.3.
+tls = true
+
+# Path to the certificate authority bundle file in PEM format.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+.RE
+.fi
+.PP
+The root CA cert
+(\fIcacert.pem\fR)
+must be installed on the system running
+\fBsudo_logsrvd\fR.
+If peer authentication is enabled on the client, a copy of
+\fIcacert.pem\fR
+must be present on the client system too.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo_logsrvd.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@),
+sudo_sendlog(@mansectsu@),
+sudoreplay(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo_logsrvd\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo_logsrvd\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_logsrvd.mdoc.in b/doc/sudo_logsrvd.mdoc.in
new file mode 100644
index 0000000..9d436c7
--- /dev/null
+++ b/doc/sudo_logsrvd.mdoc.in
@@ -0,0 +1,396 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.Dd March 28, 2020
+.Dt SUDO_LOGSRVD @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrvd
+.Nd sudo event and I/O log server
+.Sh SYNOPSIS
+.Nm sudo_logsrvd
+.Op Fl hnV
+.Op Fl f Ar file
+.Op Fl R Ar percentage
+.Sh DESCRIPTION
+.Nm
+is a high-performance log server that accepts event and I/O logs from
+.Nm sudo .
+It can be used to implement centralized logging of
+.Nm sudo
+logs.
+Event log entries may be logged either via
+.Xr syslog 3
+or to a file.
+I/O Logs created by
+.Nm
+can be replayed via the
+.Xr sudoreplay @mansectsu@
+utility in the same way as logs generated directly by the
+.Nm sudoers
+plugin.
+.Pp
+The server also supports restarting interrupted log transfers.
+To distinguish completed I/O logs from incomplete ones, the
+I/O log timing file is set to be read-only when the log is complete.
+.Pp
+Configuration parameters for
+.Nm
+may be specified in the
+.Xr sudo_logsrvd.conf @mansectform@
+file.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl f , -file
+Read configuration from
+.Ar file
+instead of the default,
+.Pa @sysconfdir@/sudo_logsrvd.conf .
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl n , -no-fork
+Run
+.Nm
+in the foreground instead of detaching from the terminal and becoming
+a daemon.
+.It Fl R , -random-drop
+For each message, there is a
+.Ar percentage
+chance that the server will drop the connection.
+This is only intended for debugging the ability of a
+client to restart a connection.
+.It Fl V , -version
+Print the
+.Nm
+version and exit.
+.El
+.Ss Securing server connections
+The I/O log data sent to
+.Nm
+may contain sensitive information such as passwords and should be
+secured using Transport Layer Security (TLS).
+Doing so requires having a signed certificate on the server and, if
+.Em tls_checkpeer
+is enabled in
+.Xr sudo_logsrvd.conf @mansectform@ ,
+a signed certificate on the client as well.
+.Pp
+The certificates can either be signed by a well-known Certificate
+Authority (CA), or a private CA can be used.
+Instructions for creating a private CA are included below in the
+.Sx EXAMPLES
+section.
+.Ss Debugging sudo_logsrvd
+.Nm
+supports a flexible debugging framework that is configured via
+.Li Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+please refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front end configuration
+.It Pa @sysconfdir@/sudo_logsrvd.conf
+Sudo log server configuration file
+.It Pa @iolog_dir@
+Default I/O log file location
+.It Pa @rundir@/sudo_logsrvd.pid
+Process ID file for
+.Nm
+.El
+.Sh EXAMPLES
+.Ss Creating self-signed certificates
+Unless you are using certificates signed by a well-known Certificate
+Authority (or a local enterprise CA), you will need to create your
+own CA that can sign the certificates used by
+.Nm ,
+.Nm sudo_sendlog ,
+and the
+.Nm sudoers
+plugin.
+The following steps use the
+.Xr openssl 1
+command to create keys and certificates.
+.Ss Initial setup
+First, we need to create a directory structure to store the
+files for the CA.
+We'll create a new directory hierarchy in
+.Pa /etc/ssl/sudo
+for this purpose.
+.Bd -literal -offset indent
+# mkdir /etc/ssl/sudo
+# cd /etc/ssl/sudo
+# mkdir certs csr newcerts private
+# chmod 700 private
+# touch index.txt
+# echo 1000 > serial
+.Ed
+.Pp
+The serial and index.txt files are used to keep track of signed certificates.
+.Pp
+Next, we need to make a copy of the openssl.conf file and customize
+it for our new CA.
+The path to openssl.cnf is system-dependent but
+.Pa /etc/ssl/openssl.cnf
+is the most common location.
+You will need to adjust the example below if it has a different location on
+your system.
+.Bd -literal -offset indent
+# cp /etc/ssl/openssl.cnf .
+.Ed
+.Pp
+Now edit the
+.Pa openssl.cnf
+file in the current directory and make sure it contains
+.Dq ca
+and
+.Dq CA_default
+sections.
+Those sections should include the following settings:
+.Bd -literal -offset indent
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = /etc/ssl/sudo
+certs = $dir/certs
+database = $dir/index.txt
+certificate = $dir/cacert.pem
+serial = $dir/serial
+.Ed
+.Pp
+If your
+.Pa openssl.conf
+file already has a
+.Dq CA_default
+section, you may only need to modify the
+.Dq dir
+setting.
+.Ss Creating the CA key and certificate
+In order to create and sign our own certificates, we need to create
+a private key and a certificate for the root of the CA.
+First, create the private key and protect it with a pass phrase:
+.Bd -literal -offset indent
+# openssl genrsa -aes256 -out private/cakey.pem 4096
+# chmod 400 private/cakey.pem
+.Ed
+.Pp
+Next, generate the root certificate, using appropriate values for
+the site-specific fields:
+.Bd -literal -offset indent
+# openssl req -config openssl.cnf -key private/cakey.pem \e
+ -new -x509 -days 7300 -sha256 -extensions v3_ca \e
+ -out cacert.pem
+
+Enter pass phrase for private/cakey.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo Certificate Authority
+Common Name (e.g., server FQDN or YOUR name) []:sudo Root CA
+Email Address []:
+
+# chmod 444 cacert.pem
+.Ed
+.Pp
+Finally, verify the root certificate:
+.Bd -literal -offset indent
+# openssl x509 -noout -text -in cacert.pem
+.Ed
+.Ss Creating and signing certificates
+The server and client certificates will be signed by the previously
+created root CA.
+Usually, the root CA is not used to sign server/client certificates
+directly.
+Instead, intermediate certificates are created and signed with the
+root CA and the intermediate certs are used to sign CSRs (Certificate
+Signing Request).
+In this example we'll skip this part for simplicity's sake and sign the
+CSRs with the root CA.
+.Pp
+First, generate the private key without a pass phrase.
+.Bd -literal -offset indent
+# openssl genrsa -out private/logsrvd_key.pem 2048
+# chmod 400 private/logsrvd_key.pem
+.Ed
+.Pp
+Next, create a certificate signing request (CSR) for the server's certificate.
+The organization name must match the name given in the root certificate.
+The common name should be either the server's IP address or a fully
+qualified domain name.
+.Bd -literal -offset indent
+# openssl req -config openssl.cnf -key private/logsrvd_key.pem -new \e
+ -sha256 -out csr/logsrvd_csr.pem
+
+Enter pass phrase for private/logsrvd_key.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo log server
+Common Name (e.g., server FQDN or YOUR name) []:logserver.example.com
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+.Ed
+.Pp
+Now sign the CSR that was just created:
+.Bd -literal -offset indent
+# openssl ca -config openssl.cnf -days 375 -notext -md sha256 \e
+ -in csr/logsrvd_csr.pem -out certs/logsrvd_cert.pem
+
+Using configuration from openssl.cnf
+Enter pass phrase for ./private/cakey.pem:
+Check that the request matches the signature
+Signature ok
+Certificate Details:
+ Serial Number: 4096 (0x1000)
+ Validity
+ Not Before: Nov 11 14:05:05 2019 GMT
+ Not After : Nov 20 14:05:05 2020 GMT
+ Subject:
+ countryName = US
+ stateOrProvinceName = Colorado
+ organizationName = sudo
+ organizationalUnitName = sudo log server
+ commonName = logserve.example.com
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 4C:50:F9:D0:BE:1A:4C:B2:AC:90:76:56:C7:9E:16:AE:E6:9E:E5:B5
+ X509v3 Authority Key Identifier:
+ keyid:D7:91:24:16:B1:03:06:65:1A:7A:6E:CF:51:E9:5C:CB:7A:95:3E:0C
+
+Certificate is to be certified until Nov 20 14:05:05 2020 GMT (375 days)
+Sign the certificate? [y/n]:y
+
+1 out of 1 certificate requests certified, commit? [y/n]y
+Write out database with 1 new entries
+Data Base Updated
+.Ed
+.Pp
+Finally, verify the new certificate:
+.Bd -literal -offset indent
+# openssl verify -CAfile cacert.pem certs/logsrvd_cert.pem
+certs/logsrvd_cert.pem: OK
+.Ed
+.Pp
+The
+.Pa /etc/ssl/sudo/certs
+directory now contains a signed and verified certificate for use with
+.Nm sudo_logsrvd .
+.Pp
+To generate a client certificate, repeat the process above using
+a different file name.
+.Ss Configuring sudo_logsrvd to use TLS
+To use TLS for client/server communication, both
+.Nm
+and the
+.Nm sudoers
+plugin need to be configured to use TLS.
+Configuring
+.Nm
+for TLS requires the following settings, assuming the same path
+names used earlier:
+.Bd -literal -offset indent
+# If set, secure connections with TLS 1.2 or 1.3.
+tls = true
+
+# Path to the certificate authority bundle file in PEM format.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+.Ed
+.Pp
+The root CA cert
+.Pq Pa cacert.pem
+must be installed on the system running
+.Nm .
+If peer authentication is enabled on the client, a copy of
+.Pa cacert.pem
+must be present on the client system too.
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_logsrvd.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_sendlog @mansectsu@ ,
+.Xr sudoreplay @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in
new file mode 100644
index 0000000..712a714
--- /dev/null
+++ b/doc/sudo_plugin.man.in
@@ -0,0 +1,5147 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2020 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.
+.\"
+.TH "SUDO_PLUGIN" "5" "November 17, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_plugin\fR
+\- Sudo Plugin API
+.SH "DESCRIPTION"
+Starting with version 1.8,
+\fBsudo\fR
+supports a plugin API
+for policy and session logging.
+Plugins may be compiled as dynamic shared objects (the default on
+systems that support them) or compiled statically into the
+\fBsudo\fR
+binary itself.
+By default, the
+\fBsudoers\fR
+policy plugin and an associated I/O logging plugin are used.
+Via the plugin API,
+\fBsudo\fR
+can be configured to use alternate policy and/or I/O logging plugins
+provided by third parties.
+The plugins to be used are specified in the
+sudo.conf(@mansectform@)
+file.
+.PP
+The API is versioned with a major and minor number.
+The minor version number is incremented when additions are made.
+The major number is incremented when incompatible changes are made.
+A plugin should be check the version passed to it and make sure that the
+major version matches.
+.PP
+The plugin API is defined by the
+\fRsudo_plugin.h\fR
+header file.
+.SS "Policy plugin API"
+A policy plugin must declare and populate a
+\fRpolicy_plugin\fR
+struct in the global scope.
+This structure contains pointers to the functions that implement the
+\fBsudo\fR
+policy checks.
+The name of the symbol should be specified in
+sudo.conf(@mansectform@)
+along with a path to the plugin so that
+\fBsudo\fR
+can load it.
+.nf
+.sp
+.RS 0n
+struct policy_plugin {
+#define SUDO_POLICY_PLUGIN 1
+ 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 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);
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ 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);
+ int (*validate)(const char **errstr);
+ void (*invalidate)(int remove);
+ int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.RE
+.fi
+.PP
+The policy_plugin struct has the following fields:
+.TP 6n
+type
+The
+\fRtype\fR
+field should always be set to SUDO_POLICY_PLUGIN.
+.TP 6n
+version
+The
+\fRversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+open
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+version
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+conversation
+A pointer to the
+\fBconversation\fR()
+function that can be used by the plugin to interact with the user (see
+\fIConversation API\fR
+for details).
+Returns 0 on success and \-1 on failure.
+.TP 6n
+plugin_printf
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error messages (see
+\fIConversation API\fR
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+settings
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+The following values may be set by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+bsdauth_type=string
+Authentication type, if specified by the
+\fB\-a\fR
+option, to use on
+systems where
+BSD
+authentication is supported.
+.PD
+.TP 6n
+closefrom=number
+If specified, the user has requested via the
+\fB\-C\fR
+option that
+\fBsudo\fR
+close all files descriptors with a value of
+\fInumber\fR
+or higher.
+The plugin may optionally pass this, or another value, back in the
+\fIcommand_info\fR
+list.
+.TP 6n
+cmnd_chroot=string
+The root directory (see
+chroot(2))
+to run the command in, as specified by the user via the
+\fB\-R\fR
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+root directory.
+Only available starting with API version 1.16.
+.TP 6n
+cmnd_cwd=string
+The working directory to run the command in, as specified by the user via the
+\fB\-D\fR
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+working directory.
+Only available starting with API version 1.16.
+.TP 6n
+debug_flags=string
+A debug file path name followed by a space and a comma-separated
+list of debug flags that correspond to the plugin's
+\fRDebug\fR
+entry in
+sudo.conf(@mansectform@),
+if there is one.
+The flags are passed to the plugin exactly as they appear in
+sudo.conf(@mansectform@).
+The syntax used by
+\fBsudo\fR
+and the
+\fBsudoers\fR
+plugin is
+\fIsubsystem\fR@\fIpriority\fR
+but a plugin is free to use a different
+format so long as it does not include a comma
+(\(oq,\&\(cq).
+Prior to
+\fBsudo\fR
+1.8.12, there was no way to specify plugin-specific
+\fIdebug_flags\fR
+so the value was always the same as that used by the
+\fBsudo\fR
+front end and did not include a path name, only the flags themselves.
+As of version 1.7 of the plugin interface,
+\fBsudo\fR
+will only pass
+\fIdebug_flags\fR
+if
+sudo.conf(@mansectform@)
+contains a plugin-specific
+\fRDebug\fR
+entry.
+.TP 6n
+ignore_ticket=bool
+Set to true if the user specified the
+\fB\-k\fR
+option along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+\fIimplied_shell\fR
+to true.
+This allows
+\fBsudo\fR
+with no arguments
+to be used similarly to
+su(1).
+If the plugin does not to support this usage, it may return a value of \-2
+from the
+\fBcheck_policy\fR()
+function, which will cause
+\fBsudo\fR
+to print a usage message and
+exit.
+.TP 6n
+implied_shell=bool
+If the user does not specify a program on the command line,
+\fBsudo\fR
+will pass the plugin the path to the user's shell and set
+.TP 6n
+login_class=string
+BSD
+login class to use when setting resource limits and nice value,
+if specified by the
+\fB\-c\fR
+option.
+.TP 6n
+login_shell=bool
+Set to true if the user specified the
+\fB\-i\fR
+option, indicating that
+the user wishes to run a login shell.
+.TP 6n
+max_groups=int
+The maximum number of groups a user may belong to.
+This will only be present if there is a corresponding setting in
+sudo.conf(@mansectform@).
+.TP 6n
+network_addrs=list
+A space-separated list of IP network addresses and netmasks in the
+form
+\(lqaddr/netmask\(rq,
+e.g.,
+\(lq192.168.1.2/255.255.255.0\(rq.
+The address and netmask pairs may be either IPv4 or IPv6, depending on
+what the operating system supports.
+If the address contains a colon
+(\(oq:\&\(cq),
+it is an IPv6 address, else it is IPv4.
+.TP 6n
+noninteractive=bool
+Set to true if the user specified the
+\fB\-n\fR
+option, indicating that
+\fBsudo\fR
+should operate in non-interactive mode.
+The plugin may reject a command run in non-interactive mode if user
+interaction is required.
+.TP 6n
+plugin_dir=string
+The default plugin directory used by the
+\fBsudo\fR
+front end.
+This is the default directory set at compile time and may not
+correspond to the directory the running plugin was loaded from.
+It may be used by a plugin to locate support files.
+.TP 6n
+plugin_path=string
+The path name of plugin loaded by the
+\fBsudo\fR
+front end.
+The path name will be a fully-qualified unless the plugin was
+statically compiled into
+\fBsudo\fR.
+.TP 6n
+preserve_environment=bool
+Set to true if the user specified the
+\fB\-E\fR
+option, indicating that
+the user wishes to preserve the environment.
+.TP 6n
+preserve_groups=bool
+Set to true if the user specified the
+\fB\-P\fR
+option, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+.TP 6n
+progname=string
+The command name that sudo was run as, typically
+\(lqsudo\(rq
+or
+\(lqsudoedit\(rq.
+.TP 6n
+prompt=string
+The prompt to use when requesting a password, if specified via
+the
+\fB\-p\fR
+option.
+.TP 6n
+remote_host=string
+The name of the remote host to run the command on, if specified via
+the
+\fB\-h\fR
+option.
+Support for running the command on a remote host is meant to be implemented
+via a helper program that is executed in place of the user-specified command.
+The
+\fBsudo\fR
+front end is only capable of executing commands on the local host.
+Only available starting with API version 1.4.
+.TP 6n
+run_shell=bool
+Set to true if the user specified the
+\fB\-s\fR
+option, indicating that the user wishes to run a shell.
+.TP 6n
+runas_group=string
+The group name or gid to run the command as, if specified via
+the
+\fB\-g\fR
+option.
+.TP 6n
+runas_user=string
+The user name or uid to run the command as, if specified via the
+\fB\-u\fR
+option.
+.TP 6n
+selinux_role=string
+SELinux role to use when executing the command, if specified by
+the
+\fB\-r\fR
+option.
+.TP 6n
+selinux_type=string
+SELinux type to use when executing the command, if specified by
+the
+\fB\-t\fR
+option.
+.TP 6n
+set_home=bool
+Set to true if the user specified the
+\fB\-H\fR
+option.
+If true, set the
+\fRHOME\fR
+environment variable to the target user's home directory.
+.TP 6n
+sudoedit=bool
+Set to true when the
+\fB\-e\fR
+option is specified or if invoked as
+\fBsudoedit\fR.
+The plugin shall substitute an editor into
+\fIargv\fR
+in the
+\fBcheck_policy\fR()
+function or return \-2 with a usage error
+if the plugin does not support
+\fIsudoedit\fR.
+For more information, see the
+\fIcheck_policy\fR
+section.
+.TP 6n
+timeout=string
+Command timeout specified by the user via the
+\fB\-T\fR
+option.
+Not all plugins support command timeouts and the ability of the
+user to set a timeout may be restricted by policy.
+The format of the timeout string is plugin-specific.
+.PP
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+.RE
+.TP 6n
+user_info
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+The following values may be set by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+cols=int
+The number of columns the user's terminal supports.
+If there is no terminal device available, a default value of 80 is used.
+.PD
+.TP 6n
+cwd=string
+The user's current working directory.
+.TP 6n
+egid=gid_t
+The effective group-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+euid=uid_t
+The effective user-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+gid=gid_t
+The real group-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+groups=list
+The user's supplementary group list formatted as a string of
+comma-separated group-IDs.
+.TP 6n
+host=string
+The local machine's hostname as returned by the
+gethostname(2)
+system call.
+.TP 6n
+lines=int
+The number of lines the user's terminal supports.
+If there is
+no terminal device available, a default value of 24 is used.
+.TP 6n
+pgid=int
+The ID of the process group that the running
+\fBsudo\fR
+process is a member of.
+Only available starting with API version 1.2.
+.TP 6n
+pid=int
+The process ID of the running
+\fBsudo\fR
+process.
+Only available starting with API version 1.2.
+.TP 6n
+ppid=int
+The parent process ID of the running
+\fBsudo\fR
+process.
+Only available starting with API version 1.2.
+.TP 6n
+rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+sid=int
+The session ID of the running
+\fBsudo\fR
+process or 0 if
+\fBsudo\fR
+is not part of a POSIX job control session.
+Only available starting with API version 1.2.
+.TP 6n
+tcpgid=int
+The ID of the foreground process group associated with the terminal
+device associated with the
+\fBsudo\fR
+process or 0 if there is no terminal present.
+Only available starting with API version 1.2.
+.TP 6n
+tty=string
+The path to the user's terminal device.
+If the user has no terminal device associated with the session,
+the value will be empty, as in
+\(lq\fRtty=\fR\(rq.
+.TP 6n
+uid=uid_t
+The real user-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+umask=octal
+The invoking user's file creation mask.
+Only available starting with API version 1.10.
+.TP 6n
+user=string
+The name of the user invoking
+\fBsudo\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+user_env
+The user's environment in the form of a
+\fRNULL\fR-terminated vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIuser_env\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+plugin_options
+Any (non-comment) strings immediately after the plugin path are
+passed as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were
+specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.sp
+NOTE: the
+\fIplugin_options\fR
+parameter is only available starting with
+API version 1.2.
+A plugin
+\fBmust\fR
+check the API version specified
+by the
+\fBsudo\fR
+front end before using
+\fIplugin_options\fR.
+Failure to do so may result in a crash.
+.TP 6n
+errstr
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+close
+.br
+.nf
+.RS 6n
+void (*close)(int exit_status, int error);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+Starting with API version 1.15,
+\fBclose\fR()
+is called regardless of whether or not a command was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+It is not possible to tell whether a command was run based solely
+on the arguments passed to the
+\fBclose\fR()
+function.
+To determine if a command was actually run,
+the plugin must keep track of whether or not the
+\fBcheck_policy\fR()
+function returned successfully.
+.sp
+The function arguments are as follows:
+.TP 6n
+exit_status
+The command's exit status, as returned by the
+wait(2)
+system call, or zero if no command was run.
+The value of
+\fRexit_status\fR
+is undefined if
+\fRerror\fR
+is non-zero.
+.TP 6n
+error
+.br
+If the command could not be executed, this is set to the value of
+\fRerrno\fR
+set by the
+execve(2)
+system call.
+The plugin is responsible for displaying error information via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function.
+If the command was successfully executed, the value of
+\fRerror\fR
+is zero.
+.PP
+If no
+\fBclose\fR()
+function is defined, no I/O logging plugins are loaded,
+and neither the
+\fItimeout\fR
+not
+\fIuse_pty\fR
+options are set in the
+\fRcommand_info\fR
+list, the
+\fBsudo\fR
+front end may execute the command directly instead of running
+it as a child process.
+.RE
+.TP 6n
+show_version
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies
+the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the verbose flag will be set.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+check_policy
+.nf
+.RS 6n
+int (*check_policy)(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **argv_out[], char **user_env_out[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcheck_policy\fR()
+function is called by
+\fBsudo\fR
+to determine
+whether the user is allowed to run the specified commands.
+.sp
+If the
+\fIsudoedit\fR
+option was enabled in the
+\fIsettings\fR
+array
+passed to the
+\fBopen\fR()
+function, the user has requested
+\fIsudoedit\fR
+mode.
+\fIsudoedit\fR
+is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.
+\fBsudo\fR
+achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.
+If the plugin supports
+\fIsudoedit\fR,
+it should choose the editor to be used, potentially from a variable
+in the user's environment, such as
+\fREDITOR\fR,
+and include it in
+\fIargv_out\fR
+(note that environment
+variables may include command line options).
+The files to be edited should be copied from
+\fIargv\fR
+into
+\fIargv_out\fR,
+separated from the
+editor and its arguments by a
+\(lq\fR--\fR\(rq
+element.
+The
+\(lq\fR--\fR\(rq
+will
+be removed by
+\fBsudo\fR
+before the editor is executed.
+The plugin should also set
+\fIsudoedit=true\fR
+in the
+\fIcommand_info\fR
+list.
+.sp
+The
+\fBcheck_policy\fR()
+function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if
+\fIsudoedit\fR
+was specified but is unsupported by the plugin.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it
+exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+argc
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+.TP 6n
+argv
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the
+execve(2)
+system call.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.TP 6n
+env_add
+Additional environment variables specified by the user on the command
+line in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+.sp
+When parsing
+\fIenv_add\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+command_info
+Information about the command being run in the form of
+\(lqname=value\(rq
+strings.
+These values are used by
+\fBsudo\fR
+to set the execution
+environment when running a command.
+The plugin is responsible for creating and populating the vector,
+which must be terminated with a
+\fRNULL\fR
+pointer.
+The following values are recognized by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+chroot=string
+The root directory to use when running the command.
+.PD
+.TP 6n
+closefrom=number
+If specified,
+\fBsudo\fR
+will close all files descriptors with a value
+of
+\fInumber\fR
+or higher.
+.TP 6n
+command=string
+Fully qualified path to the command to be executed.
+.TP 6n
+cwd=string
+The current working directory to change to when executing the command.
+If
+\fBsudo\fR
+is unable to change to the new working directory, the command will
+not be run unless
+\fIcwd_optional\fR
+is also set (see below).
+.TP 6n
+cwd_optional=bool
+If enabled,
+\fBsudo\fR
+will treat an inability to change to the new working directory as a
+non-fatal error.
+This setting has no effect unless
+\fIcwd\fR
+is also set.
+.TP 6n
+exec_background=bool
+By default,
+\fBsudo\fR
+runs a command as the foreground process as long as
+\fBsudo\fR
+itself is running in the foreground.
+When
+\fIexec_background\fR
+is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+\fIuse_pty\fR
+setting), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+\fRSIGTTIN\fR
+signal (or
+\fRSIGTTOU\fR
+in the case of terminal settings).
+If this happens when
+\fBsudo\fR
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+\fBsudo\fR
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+\fIsudo\fR
+behavior or when the command is not being run in a pseudo-terminal.
+.sp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+\fBtcgetattr\fR()
+and
+\fBtcsetattr\fR()
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+\fRSIGTTIN\fR
+or
+\fRSIGTTOU\fR
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+\fRSIGTOP\fR)
+will not be automatically foregrounded.
+Some versions of the linux
+su(1)
+command behave this way.
+Because of this, a plugin should not set
+\fIexec_background\fR
+unless it is explicitly enabled by the administrator and there should
+be a way to enabled or disable it on a per-command basis.
+.sp
+This setting has no effect unless I/O logging is enabled or
+\fIuse_pty\fR
+is enabled.
+.TP 6n
+execfd=number
+If specified,
+\fBsudo\fR
+will use the
+fexecve(2)
+system call to execute the command instead of
+execve(2).
+The specified
+\fInumber\fR
+must refer to an open file descriptor.
+.TP 6n
+iolog_compress=bool
+Set to true if the I/O logging plugins, if any, should compress the
+log data.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_group=string
+The group that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_mode=octal
+The file permission mode to use when creating I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_user=string
+The user that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_path=string
+Fully qualified path to the file or directory in which I/O log is
+to be stored.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+If no I/O logging plugin is loaded, this setting has no effect.
+.TP 6n
+iolog_stdin=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_stdout=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_stderr=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_ttyin=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.
+This only includes input typed by the user and not from a pipe or
+redirected from a file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_ttyout=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.
+This only includes output to the screen, not output to a pipe or file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+login_class=string
+BSD
+login class to use when setting resource limits and nice value (optional).
+This option is only set on systems that support login classes.
+.TP 6n
+nice=int
+Nice value (priority) to use when executing the command.
+The nice value, if specified, overrides the priority associated with the
+\fIlogin_class\fR
+on
+BSD
+systems.
+.TP 6n
+noexec=bool
+If set, prevent the command from executing other programs.
+.TP 6n
+preserve_fds=list
+A comma-separated list of file descriptors that should be
+preserved, regardless of the value of the
+\fIclosefrom\fR
+setting.
+Only available starting with API version 1.5.
+.TP 6n
+preserve_groups=bool
+If set,
+\fBsudo\fR
+will preserve the user's group vector instead of
+initializing the group vector based on
+\fRrunas_user\fR.
+.TP 6n
+runas_egid=gid
+Effective group-ID to run the command as.
+If not specified, the value of
+\fIrunas_gid\fR
+is used.
+.TP 6n
+runas_euid=uid
+Effective user-ID to run the command as.
+If not specified, the value of
+\fIrunas_uid\fR
+is used.
+.TP 6n
+runas_gid=gid
+Group-ID to run the command as.
+.TP 6n
+runas_group=string
+The name of the group the command will run as, if it is different
+from the
+\fIrunas_user\fR's
+default group.
+This value is provided for auditing purposes only, the
+\fBsudo\fR
+front-end uses
+\fIrunas_egid\fR
+and
+\fIrunas_gid\fR
+when executing the command.
+.TP 6n
+runas_groups=list
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group-IDs.
+If
+\fIpreserve_groups\fR
+is set, this option is ignored.
+.TP 6n
+runas_uid=uid
+User-ID to run the command as.
+.TP 6n
+runas_user=string
+The name of the user the command will run as, which should correspond to
+\fIrunas_euid\fR
+(or
+\fIrunas_uid\fR
+if
+\fIrunas_euid\fR
+is not set).
+This value is provided for auditing purposes only, the
+\fBsudo\fR
+front-end uses
+\fIrunas_euid\fR
+and
+\fIrunas_uid\fR
+when executing the command.
+.TP 6n
+selinux_role=string
+SELinux role to use when executing the command.
+.TP 6n
+selinux_type=string
+SELinux type to use when executing the command.
+.TP 6n
+set_utmp=bool
+Create a utmp (or utmpx) entry when a pseudo-terminal is allocated.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+.TP 6n
+sudoedit=bool
+Set to true when in
+\fIsudoedit\fR
+mode.
+The plugin may enable
+\fIsudoedit\fR
+mode even if
+\fBsudo\fR
+was not invoked as
+\fBsudoedit\fR.
+This allows the plugin to perform command substitution and transparently
+enable
+\fIsudoedit\fR
+when the user attempts to run an editor.
+.TP 6n
+sudoedit_checkdir=bool
+Set to false to disable directory writability checks in
+\fBsudoedit\fR.
+By default,
+\fBsudoedit\fR
+1.8.16 and higher will check all directory components of the path to be
+edited for writability by the invoking user.
+Symbolic links will not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+\fBsudoedit\fR
+is run by root.
+The
+\fIsudoedit_follow\fR
+option can be set to false to disable this check.
+Only available starting with API version 1.8.
+.TP 6n
+sudoedit_follow=bool
+Set to true to allow
+\fBsudoedit\fR
+to edit files that are symbolic links.
+By default,
+\fBsudoedit\fR
+1.8.15 and higher will refuse to open a symbolic link.
+The
+\fIsudoedit_follow\fR
+option can be used to restore the older behavior and allow
+\fBsudoedit\fR
+to open symbolic links.
+Only available starting with API version 1.8.
+.TP 6n
+timeout=int
+Command timeout.
+If non-zero then when the timeout expires the command will be killed.
+.TP 6n
+umask=octal
+The file creation mask to use when executing the command.
+This value may be overridden by PAM or login.conf on some systems
+unless the
+\fIumask_override\fR
+option is also set.
+.TP 6n
+umask_override=bool
+Force the value specified by the
+\fIumask\fR
+option to override any umask set by PAM or login.conf.
+.TP 6n
+use_pty=bool
+Allocate a pseudo-terminal to run the command in, regardless of whether
+or not I/O logging is in use.
+By default,
+\fBsudo\fR
+will only run
+the command in a pseudo-terminal when an I/O log plugin is loaded.
+.TP 6n
+utmp_user=string
+User name to use when constructing a new utmp (or utmpx) entry when
+\fIset_utmp\fR
+is enabled.
+This option can be used to set the user field in the utmp entry to
+the user the command runs as rather than the invoking user.
+If not set,
+\fBsudo\fR
+will base the new entry on
+the invoking user's existing entry.
+.PP
+Unsupported values will be ignored.
+.RE
+.TP 6n
+argv_out
+The
+\fRNULL\fR-terminated
+argument vector to pass to the
+execve(2)
+system call when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.TP 6n
+user_env_out
+The
+\fRNULL\fR-terminated
+environment vector to use when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.TP 6n
+errstr
+If the
+\fBcheck_policy\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+list
+.nf
+.RS 6n
+int (*list)(int argc, char * const argv[], int verbose,
+ const char *list_user, const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+List available privileges for the invoking user.
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to
+the user.
+.sp
+Privileges should be output via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+.sp
+The function arguments are as follows:
+.TP 6n
+argc
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+.TP 6n
+argv
+If
+non-\fRNULL\fR,
+an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the
+execve(2)
+system call.
+If the command is permitted by the policy, the fully-qualified path
+to the command should be displayed along with any command line arguments.
+.TP 6n
+verbose
+Flag indicating whether to list in verbose mode or not.
+.TP 6n
+list_user
+The name of a different user to list privileges for if the policy
+allows it.
+If
+\fRNULL\fR,
+the plugin should list the privileges of the invoking user.
+.TP 6n
+errstr
+If the
+\fBlist\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+validate
+.nf
+.RS 6n
+int (*validate)(const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBvalidate\fR()
+function is called when
+\fBsudo\fR
+is run with the
+\fB\-v\fR
+option.
+For policy plugins such as
+\fBsudoers\fR
+that cache
+authentication credentials, this function will validate and cache
+the credentials.
+.sp
+The
+\fBvalidate\fR()
+function should be
+\fRNULL\fR
+if the plugin does not support credential caching.
+.sp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional
+error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+errstr
+If the
+\fBvalidate\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+invalidate
+.nf
+.RS 6n
+void (*invalidate)(int remove);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinvalidate\fR()
+function is called when
+\fBsudo\fR
+is run with the
+\fB\-k\fR
+or
+\fB\-K\fR
+option.
+For policy plugins such as
+\fBsudoers\fR
+that
+cache authentication credentials, this function will invalidate the
+credentials.
+If the
+\fIremove\fR
+flag is set, the plugin may remove
+the credentials instead of simply invalidating them.
+.sp
+The
+\fBinvalidate\fR()
+function should be
+\fRNULL\fR
+if the plugin does not support credential caching.
+.RE
+.TP 6n
+init_session
+.nf
+.RS 6n
+int (*init_session)(struct passwd *pwd, char **user_env_out[]);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinit_session\fR()
+function is called before
+\fBsudo\fR
+sets up the
+execution environment for the command.
+It is run in the parent
+\fBsudo\fR
+process and before any uid or gid changes.
+This can be used to perform session setup that is not supported by
+\fIcommand_info\fR,
+such as opening the PAM session.
+The
+\fBclose\fR()
+function can be
+used to tear down the session that was opened by
+\fRinit_session\fR.
+.sp
+The
+\fIpwd\fR
+argument points to a passwd struct for the user the
+command will be run as if the uid the command will run as was found
+in the password database, otherwise it will be
+\fRNULL\fR.
+.sp
+The
+\fIuser_env_out\fR
+argument points to the environment the command will
+run in, in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+This is the same string passed back to the front end via
+the Policy Plugin's
+\fIuser_env_out\fR
+parameter.
+If the
+\fBinit_session\fR()
+function needs to modify the user environment, it should update the
+pointer stored in
+\fIuser_env_out\fR.
+The expected use case is to merge the contents of the PAM environment
+(if any) with the contents of
+\fIuser_env_out\fR.
+NOTE: the
+\fIuser_env_out\fR
+parameter is only available
+starting with API version 1.2.
+A plugin
+\fBmust\fR
+check the API
+version specified by the
+\fBsudo\fR
+front end before using
+\fIuser_env_out\fR.
+Failure to do so may result in a crash.
+.sp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional
+error information to the user.
+.RE
+.TP 6n
+register_hooks
+.nf
+.RS 6n
+void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBregister_hooks\fR()
+function is called by the sudo front end to
+register any hooks the plugin needs.
+If the plugin does not support hooks,
+\fRregister_hooks\fR
+should be set to the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIversion\fR
+argument describes the version of the hooks API
+supported by the
+\fBsudo\fR
+front end.
+.sp
+The
+\fBregister_hook\fR()
+function should be used to register any supported
+hooks the plugin needs.
+It returns 0 on success, 1 if the hook type is not supported and \-1
+if the major version in
+\fRstruct hook\fR
+does not match the front end's major hook API version.
+.sp
+See the
+\fIHook function API\fR
+section below for more information
+about hooks.
+.sp
+NOTE: the
+\fBregister_hooks\fR()
+function is only available starting
+with API version 1.2.
+If the
+\fBsudo\fR
+front end doesn't support API
+version 1.2 or higher,
+\fRregister_hooks\fR
+will not be called.
+.RE
+.TP 6n
+deregister_hooks
+.nf
+.RS 6n
+void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBderegister_hooks\fR()
+function is called by the sudo front end
+to deregister any hooks the plugin has registered.
+If the plugin does not support hooks,
+\fRderegister_hooks\fR
+should be set to the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIversion\fR
+argument describes the version of the hooks API
+supported by the
+\fBsudo\fR
+front end.
+.sp
+The
+\fBderegister_hook\fR()
+function should be used to deregister any
+hooks that were put in place by the
+\fBregister_hook\fR()
+function.
+If the plugin tries to deregister a hook that the front end does not support,
+\fRderegister_hook\fR
+will return an error.
+.sp
+See the
+\fIHook function API\fR
+section below for more information
+about hooks.
+.sp
+NOTE: the
+\fBderegister_hooks\fR()
+function is only available starting
+with API version 1.2.
+If the
+\fBsudo\fR
+front end doesn't support API
+version 1.2 or higher,
+\fRderegister_hooks\fR
+will not be called.
+.RE
+.TP 6n
+event_alloc
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fRstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fBevent_alloc\fR()
+pointer is filled in by the
+\fBsudo\fR
+front end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+NOTE: the
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.15.
+If the
+\fBsudo\fR
+front end doesn't support API
+version 1.15 or higher,
+\fBevent_alloc\fR()
+will not be set.
+.RE
+.TP 6n
+errstr
+If the
+\fBinit_session\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PP
+\fIPolicy Plugin Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Plugin API version major/minor. */
+#define SUDO_API_VERSION_MAJOR 1
+#define SUDO_API_VERSION_MINOR 13
+#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
+ SUDO_API_VERSION_MINOR)
+
+/* Getters and setters for API version */
+#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+} while(0)
+#define SUDO_API_VERSION_SET_MINOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0xffff0000) | (n); \e
+} while(0)
+.RE
+.fi
+.SS "I/O plugin API"
+.nf
+.RS 0n
+struct io_plugin {
+#define SUDO_IO_PLUGIN 2
+ 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 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);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+ int (*log_suspend)(int signo, const char **errstr);
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.RE
+.fi
+.PP
+When an I/O plugin is loaded,
+\fBsudo\fR
+runs the command in a pseudo-terminal.
+This makes it possible to log the input and output from the user's
+session.
+If any of the standard input, standard output or standard error do not
+correspond to a tty,
+\fBsudo\fR
+will open a pipe to capture
+the I/O for logging before passing it on.
+.PP
+The log_ttyin function receives the raw user input from the terminal
+device (note that this will include input even when echo is disabled,
+such as when a password is read).
+The log_ttyout function receives output from the pseudo-terminal that is
+suitable for replaying the user's session at a later time.
+The
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR()
+and
+\fBlog_stderr\fR()
+functions are only called if the standard input, standard output
+or standard error respectively correspond to something other than
+a tty.
+.PP
+Any of the logging functions may be set to the
+\fRNULL\fR
+pointer if no logging is to be performed.
+If the open function returns 0, no I/O will be sent to the plugin.
+.PP
+If a logging function returns an error
+(\-1),
+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
+If an input logging function rejects the data by returning 0, the
+command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning 0, 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.
+.PP
+The audit_plugin struct has the following fields:
+.TP 6n
+type
+The
+\fRtype\fR
+field should always be set to
+\fRSUDO_IO_PLUGIN\fR.
+.TP 6n
+version
+The
+\fRversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+open
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t 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[]);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBopen\fR()
+function is run before the
+\fBlog_ttyin\fR(),
+\fBlog_ttyout\fR(),
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR(),
+\fBlog_stderr\fR(),
+\fBlog_suspend\fR(),
+\fBchange_winsize\fR(),
+or
+\fBshow_version\fR()
+functions are called.
+It is only called if the version is being requested or if the
+policy plugin's
+\fBcheck_policy\fR()
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+version
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+conversation
+A pointer to the
+\fBconversation\fR()
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+\fBshow_version\fR()
+below).
+The
+\fBconversation\fR()
+function may also be used to display additional error message to the user.
+The
+\fBconversation\fR()
+function returns 0 on success and \-1 on failure.
+.TP 6n
+plugin_printf
+A pointer to a
+\fBprintf\fR()-style
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+show_version below).
+The
+\fBplugin_printf\fR()
+function may also be used to display additional error message to the user.
+The
+\fBplugin_printf\fR()
+function returns number of characters printed on success and \-1 on failure.
+.TP 6n
+settings
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+user_info
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+command_info
+A vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+argc
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+It can be zero, when
+\fBsudo\fR
+is called with
+\fB\-V\fR.
+.TP 6n
+argv
+If
+non-\fRNULL\fR,
+an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+user_env
+The user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIuser_env\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.sp
+NOTE: the
+\fIplugin_options\fR
+parameter is only available starting with
+API version 1.2.
+A plugin
+\fBmust\fR
+check the API version specified
+by the
+\fBsudo\fR
+front end before using
+\fIplugin_options\fR.
+Failure to do so may result in a crash.
+.TP 6n
+errstr
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+close
+.br
+.nf
+.RS 6n
+void (*close)(int exit_status, int error);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+exit_status
+The command's exit status, as returned by the
+wait(2)
+system call, or zero if no command was run.
+The value of
+\fRexit_status\fR
+is undefined if
+\fRerror\fR
+is non-zero.
+.TP 6n
+error
+.br
+If the command could not be executed, this is set to the value of
+\fRerrno\fR
+set by the
+execve(2)
+system call.
+If the command was successfully executed, the value of
+\fRerror\fR
+is zero.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+show_version
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies
+the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+log_ttyin
+.nf
+.RS 6n
+int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_ttyin\fR()
+function is called whenever data can be read from
+the user but before it is passed to the running command.
+This allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data
+is rejected (which will terminate the running command) or \-1 if an
+error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+buf
+The buffer containing user input.
+.TP 6n
+len
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+errstr
+If the
+\fBlog_ttyin\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+log_ttyout
+.nf
+.RS 6n
+int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_ttyout\fR()
+function is called whenever data can be read from
+the command but before it is written to the user's terminal.
+This allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is rejected
+(which will terminate the running command) or \-1 if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+buf
+The buffer containing command output.
+.TP 6n
+len
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+errstr
+If the
+\fBlog_ttyout\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+log_stdin
+.nf
+.RS 6n
+int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stdin\fR()
+function is only used if the standard input does
+not correspond to a tty device.
+It is called whenever data can be read from the standard input but
+before it is passed to the running command.
+This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+buf
+The buffer containing user input.
+.TP 6n
+len
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+errstr
+If the
+\fBlog_stdin\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+log_stdout
+.nf
+.RS 6n
+int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stdout\fR()
+function is only used if the standard output does not correspond
+to a tty device.
+It is called whenever data can be read from the command but before
+it is written to the standard output.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+buf
+The buffer containing command output.
+.TP 6n
+len
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+errstr
+If the
+\fBlog_stdout\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+log_stderr
+.nf
+.RS 6n
+int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stderr\fR()
+function is only used if the standard error does
+not correspond to a tty device.
+It is called whenever data can be read from the command but before it
+is written to the standard error.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+buf
+The buffer containing command output.
+.TP 6n
+len
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+errstr
+If the
+\fBlog_stderr\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+register_hooks
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fRregister_hooks\fR.
+.TP 6n
+deregister_hooks
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fRderegister_hooks\fR.
+.TP 6n
+change_winsize
+.nf
+.RS 6n
+int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBchange_winsize\fR()
+function is called whenever the window size of the terminal changes from
+the initial values specified in the
+\fRuser_info\fR
+list.
+Returns \-1 if an error occurred, in which case no further calls to
+\fBchange_winsize\fR()
+will be made,
+.sp
+The function arguments are as follows:
+.TP 6n
+lines
+.br
+The number of lines (rows) in the re-sized terminal.
+.TP 6n
+cols
+The number of columns in the re-sized terminal.
+.TP 6n
+errstr
+If the
+\fBchange_winsize\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+log_suspend
+.nf
+.RS 6n
+int (*log_suspend)(int signo, const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_suspend\fR()
+function is called whenever a command is suspended or resumed.
+Logging this information makes it possible to skip the period of time when
+the command was suspended during playback of a session.
+Returns \-1 if an error occurred, in which case no further calls to
+\fBlog_suspend\fR()
+will be made,
+.sp
+The function arguments are as follows:
+.TP 6n
+signo
+.br
+The signal that caused the command to be suspended, or
+\fRSIGCONT\fR
+if the command was resumed.
+.TP 6n
+errstr
+If the
+\fBlog_suspend\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+NOTE: the
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.TP 6n
+event_alloc
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fRstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fBevent_alloc\fR()
+pointer is filled in by the
+\fBsudo\fR
+front end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+NOTE: the
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.15.
+If the
+\fBsudo\fR
+front end doesn't support API
+version 1.15 or higher,
+\fBevent_alloc\fR()
+will not be set.
+.RE
+.PP
+\fII/O Plugin Version Macros\fR
+.sp
+Same as for the
+\fIPolicy plugin API\fR.
+.RE
+.SS "Audit plugin API"
+.nf
+.RS 0n
+/* Audit plugin close function status types. */
+#define SUDO_PLUGIN_NO_STATUS 0
+#define SUDO_PLUGIN_WAIT_STATUS 1
+#define SUDO_PLUGIN_EXEC_ERROR 2
+#define SUDO_PLUGIN_SUDO_ERROR 3
+
+#define SUDO_AUDIT_PLUGIN 3
+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[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int status_type, int status);
+ int (*accept)(const char *plugin_name,
+ unsigned int plugin_type, char * const command_info[],
+ char * const run_argv[], char * const run_envp[],
+ const char **errstr);
+ int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*show_version)(int verbose);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+}
+.RE
+.fi
+.PP
+An audit plugin can be used to log successful and unsuccessful attempts
+to run
+\fBsudo\fR
+independent of the policy or any I/O plugins.
+Multiple audit plugins may be specified in
+sudo.conf(@mansectform@).
+.PP
+The audit_plugin struct has the following fields:
+.TP 6n
+type
+The
+\fRtype\fR
+field should always be set to
+\fRSUDO_AUDIT_PLUGIN\fR.
+.TP 6n
+version
+The
+\fRversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+open
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_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);
+.RE
+.fi
+.RS 6n
+.sp
+The audit
+\fBopen\fR()
+function is run before any other
+\fBsudo\fR
+plugin API functions.
+This makes it possible to audit failures in the other plugins.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+version
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+conversation
+A pointer to the
+\fBconversation\fR()
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+\fBshow_version\fR()
+below).
+The
+\fBconversation\fR()
+function may also be used to display additional error message to the user.
+The
+\fBconversation\fR()
+function returns 0 on success and \-1 on failure.
+.TP 6n
+plugin_printf
+A pointer to a
+\fBprintf\fR()-style
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+show_version below).
+The
+\fBplugin_printf\fR()
+function may also be used to display additional error message to the user.
+The
+\fBplugin_printf\fR()
+function returns number of characters printed on success and \-1 on failure.
+.TP 6n
+settings
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+user_info
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+submit_optind
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+If
+\fIsubmit_argv\fR
+only consists of options, which may be the case with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options,
+\fRsubmit_argv[submit_optind]\fR
+will evaluate to the NULL pointer.
+.TP 6n
+submit_argv
+The argument vector
+\fBsudo\fR
+was invoked with, including all command line options.
+The
+\fIsubmit_optind\fR
+argument can be used to determine the end of the command line options.
+.TP 6n
+submit_envp
+The invoking user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIsubmit_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+errstr
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+close
+.br
+.nf
+.RS 6n
+void (*close)(int status_type, int status);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+status_type
+The type of status being passed.
+One of
+\fRSUDO_PLUGIN_NO_STATUS\fR,
+\fRSUDO_PLUGIN_WAIT_STATUS\fR,
+\fRSUDO_PLUGIN_EXEC_ERROR\fR
+or
+\fRSUDO_PLUGIN_SUDO_ERROR\fR.
+.TP 6n
+status
+Depending on the value of
+\fIstatus_type\fR,
+this value is either
+ignored, the command's exit status as returned by the
+wait(2)
+system call, the value of
+\fRerrno\fR
+set by the
+execve(2)
+system call, or the value of
+\fRerrno\fR
+resulting from an error in the
+\fBsudo\fR
+front end.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+accept
+.nf
+.RS 6n
+int (*accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBaccept\fR()
+function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that accepted the command or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that accepted the command, currently either
+\fRSUDO_POLICY_PLUGIN\fR,
+\fRSUDO_POLICY_APPROVAL\fR
+or
+\fRSUDO_FRONT_END\fR.
+The
+\fBaccept\fR()
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+\fIcommand_info\fR
+may include information from an I/O logging plugin as well.
+.sp
+Typically, an audit plugin is interested in either the accept status from
+the
+\fBsudo\fR
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+\fBaccept\fR()
+and
+\fBreject\fR()
+functions will
+\fIboth\fR
+be called.
+.TP 6n
+command_info
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+run_argv
+A
+\fRNULL\fR-terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+run_envp
+The environment the command will be run with in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIrun_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+errstr
+If the
+\fBaccept\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+reject
+.nf
+.RS 6n
+int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBreject\fR()
+function is called when a command or action is rejected by a plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that rejected the command.
+.TP 6n
+plugin_type
+The type of plugin that rejected the command, currently either
+\fRSUDO_POLICY_PLUGIN\fR,
+\fRSUDO_APPROVAL_PLUGIN\fR
+or
+\fRSUDO_IO_PLUGIN\fR.
+.sp
+Unlike the
+\fBaccept\fR()
+function, the
+\fBreject\fR()
+function is not called on behalf of the
+\fBsudo\fR
+front-end.
+.TP 6n
+audit_msg
+An optional string describing the reason the command was rejected
+by the plugin.
+If the plugin did not provide a reason,
+\fIaudit_msg\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+command_info
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+errstr
+If the
+\fBreject\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+error
+.br
+.nf
+.RS 6n
+int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBerror\fR()
+function is called when a plugin or the
+\fBsudo\fR
+front-end returns an error.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that generated the error or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that generated the error, or
+\fRSUDO_FRONT_END\fR
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description,
+\fIaudit_msg\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+command_info
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+errstr
+If the
+\fBerror\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+show_version
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies
+the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the verbose flag will be set.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+register_hooks
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fRregister_hooks\fR.
+.TP 6n
+deregister_hooks
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fRderegister_hooks\fR.
+.TP 6n
+event_alloc
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fRstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fBevent_alloc\fR()
+pointer is filled in by the
+\fBsudo\fR
+front end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+NOTE: the
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.17.
+If the
+\fBsudo\fR
+front end doesn't support API
+version 1.17 or higher,
+\fBevent_alloc\fR()
+will not be set.
+.RE
+.SS "Approval plugin API"
+.nf
+.RS 0n
+struct approval_plugin {
+#define SUDO_APPROVAL_PLUGIN 4
+ 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[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(void);
+ int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*show_version)(int verbose);
+};
+.RE
+.fi
+.PP
+An approval plugin can be used to apply extra constraints after a
+command has been accepted by the policy plugin.
+Unlike the other plugin types, it does not remain open until the command
+completes.
+The plugin is opened before a call to
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+and closed shortly thereafter (audit plugin functions must be called
+before the plugin is closed).
+Multiple approval plugins may be specified in
+sudo.conf(@mansectform@).
+.PP
+The approval_plugin struct has the following fields:
+.TP 6n
+type
+The
+\fRtype\fR
+field should always be set to
+\fRSUDO_APPROVAL_PLUGIN\fR.
+.TP 6n
+version
+The
+\fRversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+open
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_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);
+.RE
+.fi
+.RS 6n
+.sp
+The approval
+\fBopen\fR()
+function is run immediately before a call to the plugin's
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+functions.
+It is only called if the version is being requested or if the
+policy plugin's
+\fBcheck_policy\fR()
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+version
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+conversation
+A pointer to the
+\fBconversation\fR()
+function that can be used by the plugin to interact with the user (see
+\fIConversation API\fR
+for details).
+Returns 0 on success and \-1 on failure.
+.TP 6n
+plugin_printf
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error messages (see
+\fIConversation API\fR
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+settings
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+user_info
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+submit_optind
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+If
+\fIsubmit_argv\fR
+only consists of options, which may be the case with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options,
+\fRsubmit_argv[submit_optind]\fR
+will evaluate to the NULL pointer.
+.TP 6n
+submit_argv
+The argument vector
+\fBsudo\fR
+was invoked with, including all command line options.
+The
+\fIsubmit_optind\fR
+argument can be used to determine the end of the command line options.
+.TP 6n
+submit_envp
+The invoking user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIsubmit_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+errstr
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+close
+.br
+.nf
+.RS 6n
+void (*close)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called after the approval plugin's
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+functions have been called.
+It takes no arguments.
+The
+\fBclose\fR()
+function is typically used to perform plugin-specific cleanup,
+such as the freeing of memory objects allocated by the plugin.
+If the plugin does not need to perform any cleanup,
+\fBclose\fR()
+may be set to the
+\fRNULL\fR
+pointer.
+.RE
+.TP 6n
+check
+.br
+.nf
+.RS 6n
+int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The approval
+\fBcheck\fR()
+function is run after the policy plugin
+\fBcheck_policy\fR()
+function and before any I/O logging plugins.
+If multiple approval plugins are loaded, they must all succeed for
+the command to be allowed.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+command_info
+A vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+run_argv
+A
+\fRNULL\fR-terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+run_envp
+The environment the command will be run with in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIrun_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+errstr
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+show_version
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies
+the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the verbose flag will be set.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.SS "Signal handlers"
+The
+\fBsudo\fR
+front end installs default signal handlers to trap common signals
+while the plugin functions are run.
+The following signals are trapped by default before the command is
+executed:
+.TP 3n
+\fB\(bu\fR
+\fRSIGALRM\fR
+.PD 0
+.TP 3n
+\fB\(bu\fR
+\fRSIGHUP\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGINT\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGPIPE\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGQUIT\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGTERM\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGTSTP\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGUSR1\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGUSR2\fR
+.PD
+.PP
+If a fatal signal is received before the command is executed,
+\fBsudo\fR
+will call the plugin's
+\fBclose\fR()
+function with an exit status of 128 plus the value of the signal
+that was received.
+This allows for consistent logging of commands killed by a signal
+for plugins that log such information in their
+\fBclose\fR()
+function.
+An exception to this is
+\fRSIGPIPE\fR,
+which is ignored until the command is executed.
+.PP
+A plugin may temporarily install its own signal handlers but must
+restore the original handler before the plugin function returns.
+.SS "Hook function API"
+Beginning with plugin API version 1.2, it is possible to install
+hooks for certain functions called by the
+\fBsudo\fR
+front end.
+.PP
+Currently, the only supported hooks relate to the handling of
+environment variables.
+Hooks can be used to intercept attempts to get, set, or remove
+environment variables so that these changes can be reflected in
+the version of the environment that is used to execute a command.
+A future version of the API will support hooking internal
+\fBsudo\fR
+front end functions as well.
+.PP
+\fIHook structure\fR
+.PP
+Hooks in
+\fBsudo\fR
+are described by the following structure:
+.nf
+.sp
+.RS 0n
+typedef int (*sudo_hook_fn_t)();
+
+struct sudo_hook {
+ unsigned int hook_version;
+ unsigned int hook_type;
+ sudo_hook_fn_t hook_fn;
+ void *closure;
+};
+.RE
+.fi
+.PP
+The
+\fRsudo_hook\fR
+structure has the following fields:
+.TP 6n
+hook_version
+The
+\fRhook_version\fR
+field should be set to
+\fRSUDO_HOOK_VERSION\fR.
+.TP 6n
+hook_type
+The
+\fRhook_type\fR
+field may be one of the following supported hook types:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+\fRSUDO_HOOK_SETENV\fR
+The C library
+setenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fRhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_setenv_t)(const char *name,
+ const char *value, int overwrite, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.PD
+.TP 6n
+\fRSUDO_HOOK_UNSETENV\fR
+The C library
+unsetenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fRhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
+ void *closure);
+.RE
+.fi
+.TP 6n
+\fRSUDO_HOOK_GETENV\fR
+The C library
+getenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fRhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_getenv_t)(const char *name,
+ char **value, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.TP 6n
+\fRSUDO_HOOK_PUTENV\fR
+The C library
+putenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fRhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_putenv_t)(char *string,
+ void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+hook_fn
+sudo_hook_fn_t hook_fn;
+.sp
+The
+\fRhook_fn\fR
+field should be set to the plugin's hook implementation.
+The actual function arguments will vary depending on the
+\fRhook_type\fR
+(see
+\fRhook_type\fR
+above).
+In all cases, the
+\fRclosure\fR
+field of
+\fRstruct sudo_hook\fR
+is passed as the last function parameter.
+This can be used to pass arbitrary data to the plugin's hook implementation.
+.sp
+The function return value may be one of the following:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+\fRSUDO_HOOK_RET_ERROR\fR
+The hook function encountered an error.
+.PD
+.TP 6n
+\fRSUDO_HOOK_RET_NEXT\fR
+The hook completed without error, go on to the next hook (including
+the system implementation if applicable).
+For example, a
+getenv(3)
+hook might return
+\fRSUDO_HOOK_RET_NEXT\fR
+if the specified variable was not found in the private copy of the environment.
+.TP 6n
+\fRSUDO_HOOK_RET_STOP\fR
+The hook completed without error, stop processing hooks for this invocation.
+This can be used to replace the system implementation.
+For example, a
+\fRsetenv\fR
+hook that operates on a private copy of
+the environment but leaves
+\fRenviron\fR
+unchanged.
+.PD 0
+.PP
+.RE
+.PD
+.PP
+Note that it is very easy to create an infinite loop when hooking
+C library functions.
+For example, a
+getenv(3)
+hook that calls the
+snprintf(3)
+function may create a loop if the
+snprintf(3)
+implementation calls
+getenv(3)
+to check the locale.
+To prevent this, you may wish to use a static variable in the hook
+function to guard against nested calls.
+For example:
+.nf
+.sp
+.RS 0n
+static int in_progress = 0; /* avoid recursion */
+if (in_progress)
+ return SUDO_HOOK_RET_NEXT;
+in_progress = 1;
+\&...
+in_progress = 0;
+return SUDO_HOOK_RET_STOP;
+.RE
+.fi
+.PP
+\fIHook API Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Hook API version major/minor */
+#define SUDO_HOOK_VERSION_MAJOR 1
+#define SUDO_HOOK_VERSION_MINOR 0
+#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
+ SUDO_HOOK_VERSION_MINOR)
+.RE
+.fi
+.PP
+For getters and setters see the
+\fIPolicy plugin API\fR.
+.SS "Event API"
+When
+\fBsudo\fR
+runs a command, it uses an event loop to service signals and I/O.
+Events may be triggered based on time, a file or socket descriptor
+becoming ready, or due to receipt of a signal.
+Starting with API version 1.15, it is possible for a plugin to
+participate in this event loop by calling the
+\fBevent_alloc\fR()
+function.
+.PP
+\fIEvent structure\fR
+.PP
+Events are described by the following structure:
+.nf
+.RS 0n
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure);
+
+struct sudo_plugin_event {
+ int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+ int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+ int (*del)(struct sudo_plugin_event *pev);
+ int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+ int (*fd)(struct sudo_plugin_event *pev);
+ void (*setbase)(struct sudo_plugin_event *pev, void *base);
+ void (*loopbreak)(struct sudo_plugin_event *pev);
+ void (*free)(struct sudo_plugin_event *pev);
+};
+.RE
+.fi
+.PP
+The sudo_plugin_event struct contains the following function pointers:
+.TP 6n
+\fBset\fR()
+.br
+.nf
+.RS 6n
+int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBset\fR()
+function takes the following arguments:
+.TP 6n
+struct sudo_plugin_event *\fIpev\fR
+A pointer to the struct sudo_plugin_event itself.
+.TP 6n
+\fIfd\fR
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+For time-based events,
+\fIfd\fR
+must be -1.
+.TP 6n
+\fIevents\fR
+The following values determine what will trigger the event callback:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+SUDO_PLUGIN_EV_TIMEOUT
+callback is run after the specified timeout expires
+.PD
+.TP 6n
+SUDO_PLUGIN_EV_READ
+callback is run when the file descriptor is readable
+.TP 6n
+SUDO_PLUGIN_EV_WRITE
+callback is run when the file descriptor is writable
+.TP 6n
+SUDO_PLUGIN_EV_PERSIST
+event is persistent and remains enabled until explicitly deleted
+.TP 6n
+SUDO_PLUGIN_EV_SIGNAL
+callback is run when the specified signal is received
+.PP
+The
+\fRSUDO_PLUGIN_EV_PERSIST\fR
+flag may be ORed with any of the event types.
+It is also possible to OR
+\fRSUDO_PLUGIN_EV_READ\fR
+and
+\fRSUDO_PLUGIN_EV_WRITE\fR
+together to run the callback when a descriptor is ready to be
+either read from or written to.
+All other event values are mutually exclusive.
+.RE
+.TP 6n
+sudo_plugin_ev_callback_t \fIcallback\fR
+.nf
+.RS 6n
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what,
+ void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+The function to call when an event is triggered.
+The
+\fBcallback\fR()
+function is run with the following arguments:
+.TP 6n
+\fIfd\fR
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+.TP 6n
+\fIwhat\fR
+The event type that triggered that callback.
+For events that have multiple event types (for example
+\fRSUDO_PLUGIN_EV_READ\fR
+and
+\fRSUDO_PLUGIN_EV_WRITE\fR)
+or have an associated timeout,
+\fIwhat\fR
+can be used to determine why the callback was run.
+.TP 6n
+\fIclosure\fR
+The generic pointer that was specified in the
+\fBset\fR()
+function.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+closure
+A generic pointer that will be passed to the callback function.
+.PP
+The
+\fBset\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fBadd\fR()
+.br
+.nf
+.RS 6n
+int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBadd\fR()
+function adds the event
+\fIpev\fR
+to
+\fBsudo\fR's
+event loop.
+The event must have previously been initialized via the
+\fBset\fR()
+function.
+If the
+\fItimeout\fR
+argument is not NULL, it should specify a (relative) timeout after
+which the event will be triggered if the main event criteria has
+not been met.
+This is often used to implement an I/O timeout where the event
+will fire if a descriptor is not ready within a certain time
+period.
+If the event is already present in the event loop, its
+\fItimeout\fR
+will be adjusted to match the new value, if any.
+.sp
+The
+\fBadd\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fBdel\fR()
+.br
+.nf
+.RS 6n
+int (*del)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBdel\fR()
+function deletes the event
+\fIpev\fR
+from
+\fBsudo\fR's
+event loop.
+Deleted events can be added back via the
+\fBadd\fR()
+function.
+.sp
+The
+\fBdel\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fBpending\fR()
+.nf
+.RS 6n
+int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBpending\fR()
+function can be used to determine whether one or more events is pending.
+The
+\fIevents\fR
+argument specifies which events to check for.
+See the
+\fBset\fR()
+function for a list of valid event types.
+If
+\fRSUDO_PLUGIN_EV_TIMEOUT\fR
+is specified in
+\fRevents\fR,
+the event has an associated timeout and the
+\fIts\fR
+pointer is non-NULL, it will be filled in with the remaining time.
+.RE
+.TP 6n
+\fBfd\fR()
+.nf
+.RS 6n
+int (*fd)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBfd\fR()
+function returns the descriptor or signal number associated with
+the event
+\fIpev\fR.
+.RE
+.TP 6n
+\fBsetbase\fR()
+.nf
+.RS 6n
+void (*setbase)(struct sudo_plugin_event *pev, void *base);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBsetbase\fR()
+function sets the underlying event
+\fIbase\fR
+for
+\fIpev\fR
+to the specified value.
+This can be used to move an event created via
+\fBevent_alloc\fR()
+to a new event loop allocated by sudo's event subsystem.
+If
+\fIbase\fR
+is
+\fRNULL\fR,
+\fIpev\fR's
+event base is reset to the default value, which corresponds to
+\fBsudo\fR's
+main event loop.
+Using this function requires linking the plugin with the sudo_util
+library.
+It is unlikely to be used outside of the
+\fBsudoers\fR
+plugin.
+.RE
+.TP 6n
+\fBloopbreak\fR()
+.nf
+.RS 6n
+void (*loopbreak)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBloopbreak\fR()
+function causes
+\fBsudo\fR's
+event loop to exit immediately and the running command to be terminated.
+.RE
+.TP 6n
+\fBfree\fR()
+.nf
+.RS 6n
+void (*free)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBfree\fR()
+function deletes the event
+\fIpev\fR
+from the event loop and frees the memory associated with it.
+.RE
+.SS "Remote command execution"
+The
+\fBsudo\fR
+front end does not support running remote commands.
+However, starting with
+\fBsudo\fR
+1.8.8, the
+\fB\-h\fR
+option may be used to specify a remote host that is passed
+to the policy plugin.
+A plugin may also accept a
+\fIrunas_user\fR
+in the form of
+\(lquser@hostname\(rq
+which will work with older versions of
+\fBsudo\fR.
+It is anticipated that remote commands will be supported by executing a
+\(lqhelper\(rq
+program.
+The policy plugin should setup the execution environment such that the
+\fBsudo\fR
+front end will run the helper which, in turn, will connect to the
+remote host and run the command.
+.PP
+For example, the policy plugin could utilize
+\fBssh\fR
+to perform remote command execution.
+The helper program would be responsible for running
+\fBssh\fR
+with the proper options to use a private key or certificate
+that the remote host will accept and run a program
+on the remote host that would setup the execution environment
+accordingly.
+.PP
+Note that remote
+\fBsudoedit\fR
+functionality must be handled by the policy plugin, not
+\fBsudo\fR
+itself as the front end has no knowledge that a remote command is
+being executed.
+This may be addressed in a future revision of the plugin API.
+.SS "Conversation API"
+If the plugin needs to interact with the user, it may do so via the
+\fBconversation\fR()
+function.
+A plugin should not attempt to read directly from the standard input
+or the user's tty (neither of which are guaranteed to exist).
+The caller must include a trailing newline in
+\fRmsg\fR
+if one is to be printed.
+.PP
+A
+\fBprintf\fR()-style
+function is also available that can be used to display informational
+or error messages to the user, which is usually more convenient for
+simple messages where no use input is required.
+.PP
+\fIConversation function structures\fR
+.PP
+The conversation function takes as arguments pointers to the following
+structures:
+.nf
+.sp
+.RS 0n
+struct sudo_conv_message {
+#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
+#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
+#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
+#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
+#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
+#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
+#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */
+ int msg_type;
+ int timeout;
+ const char *msg;
+};
+
+#define SUDO_CONV_REPL_MAX 1023
+
+struct sudo_conv_reply {
+ char *reply;
+};
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+ unsigned int version;
+ void *closure;
+ sudo_conv_callback_fn_t on_suspend;
+ sudo_conv_callback_fn_t on_resume;
+};
+.RE
+.fi
+.PP
+Pointers to the
+\fBconversation\fR()
+and
+\fBprintf\fR()-style
+functions are passed
+in to the plugin's
+\fBopen\fR()
+function when the plugin is initialized.
+The following type definitions can be used in the declaration of the
+\fBopen\fR()
+function:
+.nf
+.sp
+.RS 0n
+typedef int (*sudo_conv_t)(int num_msgs,
+ const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
+.RE
+.fi
+.PP
+To use the
+\fBconversation\fR()
+function, the plugin must pass an array of
+\fRsudo_conv_message\fR
+and
+\fRsudo_conv_reply\fR
+structures.
+There must be a
+\fRstruct sudo_conv_message\fR
+and
+\fRstruct sudo_conv_reply\fR
+for
+each message in the conversation, that is, both arrays must have the same
+number of elements.
+Each
+\fRstruct sudo_conv_reply\fR
+must have its
+\fIreply\fR
+member initialized to
+\fRNULL\fR.
+The
+\fRstruct sudo_conv_callback\fR
+pointer, if not
+\fRNULL\fR,
+should contain function pointers to be called when the
+\fBsudo\fR
+process is suspended and/or resumed during conversation input.
+The
+\fIon_suspend\fR
+and
+\fIon_resume\fR
+functions are called with the signal that caused
+\fBsudo\fR
+to be suspended and the
+\fIclosure\fR
+pointer from the
+\fRstruct sudo_conv_callback\fR.
+These functions should return 0 on success and \-1 on error.
+On error, the conversation will end and the conversation function
+will return a value of \-1.
+The intended use is to allow the plugin to release resources, such as locks,
+that should not be held indefinitely while suspended and then reacquire them
+when the process is resumed.
+Note that the functions are not actually invoked from within a signal handler.
+.PP
+The
+\fImsg_type\fR
+must be set to one of the following values:
+.TP 6n
+SUDO_CONV_PROMPT_ECHO_OFF
+Prompt the user for input with echo disabled;
+this is generally used for passwords.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+.TP 6n
+SUDO_CONV_PROMPT_ECHO_ON
+Prompt the user for input with echo enabled.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+.TP 6n
+SUDO_CONV_ERROR_MSG
+Display an error message.
+The message is written to the standard error unless the
+\fRSUDO_CONV_PREFER_TTY\fR
+flag is set, in which case it is written to the user's terminal if possible.
+.TP 6n
+SUDO_CONV_INFO_MSG
+Display a message.
+The message is written to the standard output unless the
+\fRSUDO_CONV_PREFER_TTY\fR
+flag is set, in which case it is written to the user's terminal if possible.
+.TP 6n
+SUDO_CONV_PROMPT_MASK
+Prompt the user for input but echo an asterisk character for each
+character read.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+This can be used to provide visual feedback to the user while reading
+sensitive information that should not be displayed.
+.PP
+In addition to the above values, the following flag bits may also be set:
+.TP 6n
+SUDO_CONV_PROMPT_ECHO_OK
+Allow input to be read when echo cannot be disabled
+when the message type is
+\fRSUDO_CONV_PROMPT_ECHO_OFF\fR
+or
+\fRSUDO_CONV_PROMPT_MASK\fR.
+By default,
+\fBsudo\fR
+will refuse to read input if the echo cannot be disabled for those
+message types.
+.TP 6n
+SUDO_CONV_PREFER_TTY
+When displaying a message via
+\fRSUDO_CONV_ERROR_MSG\fR
+or
+\fRSUDO_CONV_INFO_MSG\fR,
+try to write the message to the user's terminal.
+If the terminal is unavailable, the standard error or standard output
+will be used, depending upon whether
+The user's terminal is always used when possible for input,
+this flag is only used for output.
+\fRSUDO_CONV_ERROR_MSG\fR
+or
+\fRSUDO_CONV_INFO_MSG\fR
+was used.
+.PP
+The
+\fItimeout\fR
+in seconds until the prompt will wait for no more input.
+A zero value implies an infinite timeout.
+.PP
+The plugin is responsible for freeing the reply buffer located in each
+\fRstruct sudo_conv_reply\fR,
+if it is not
+\fRNULL\fR.
+\fRSUDO_CONV_REPL_MAX\fR
+represents the maximum length of the reply buffer (not including
+the trailing NUL character).
+In practical terms, this is the longest password
+\fBsudo\fR
+will support.
+.PP
+The
+\fBprintf\fR()-style
+function uses the same underlying mechanism as the
+\fBconversation\fR()
+function but only supports
+\fRSUDO_CONV_INFO_MSG\fR
+and
+\fRSUDO_CONV_ERROR_MSG\fR
+for the
+\fImsg_type\fR
+parameter.
+It can be more convenient than using the
+\fBconversation\fR()
+function if no user reply is needed and supports standard
+\fBprintf\fR()
+escape sequences.
+.PP
+See the sample plugin for an example of the
+\fBconversation\fR()
+function usage.
+.SS "Plugin invocation order"
+As of
+\fBsudo\fR
+1.9.0, the plugin
+\fBopen\fR()
+and
+\fBclose\fR()
+functions are called in the
+following order:
+.TP 5n
+1.\&
+audit open
+.TP 5n
+2.\&
+policy open
+.TP 5n
+3.\&
+approval open
+.TP 5n
+4.\&
+approval close
+.TP 5n
+5.\&
+I/O log open
+.TP 5n
+6.\&
+command runs
+.TP 5n
+7.\&
+command exits
+.TP 5n
+8.\&
+I/O log close
+.TP 5n
+9.\&
+policy close
+.TP 5n
+10.\&
+audit close
+.TP 5n
+11.\&
+sudo exits
+.PP
+Prior to
+\fBsudo\fR
+1.9.0, the I/O log
+\fBclose\fR()
+function was called
+\fIafter\fR
+the policy
+\fBclose\fR()
+function.
+.SS "Sudoers group plugin API"
+The
+\fBsudoers\fR
+plugin supports its own plugin interface to allow non-Unix
+group lookups.
+This can be used to query a group source other than the standard Unix
+group database.
+Two sample group plugins are bundled with
+\fBsudo\fR,
+\fIgroup_file\fR
+and
+\fIsystem_group\fR,
+are detailed in
+sudoers(@mansectform@).
+Third party group plugins include a QAS AD plugin available from Quest Software.
+.PP
+A group plugin must declare and populate a
+\fRsudoers_group_plugin\fR
+struct in the global scope.
+This structure contains pointers to the functions that implement plugin
+initialization, cleanup and group lookup.
+.nf
+.sp
+.RS 0n
+struct sudoers_group_plugin {
+ unsigned int version;
+ int (*init)(int version, sudo_printf_t sudo_printf,
+ char *const argv[]);
+ void (*cleanup)(void);
+ int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+};
+.RE
+.fi
+.PP
+The
+\fRsudoers_group_plugin\fR
+struct has the following fields:
+.TP 6n
+version
+The
+\fRversion\fR
+field should be set to GROUP_API_VERSION.
+.sp
+This allows
+\fBsudoers\fR
+to determine the API version the group plugin
+was built against.
+.TP 6n
+init
+.nf
+.RS 6n
+int (*init)(int version, sudo_printf_t plugin_printf,
+ char *const argv[]);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinit\fR()
+function is called after
+\fIsudoers\fR
+has been parsed but
+before any policy checks.
+It returns 1 on success, 0 on failure (or if the plugin is not configured),
+and \-1 if a error occurred.
+If an error occurs, the plugin may call the
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+version
+The version passed in by
+\fBsudoers\fR
+allows the plugin to determine the
+major and minor version number of the group plugin API supported by
+\fBsudoers\fR.
+.TP 6n
+plugin_printf
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error message to the user.
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+argv
+A
+\fRNULL\fR-terminated
+array of arguments generated from the
+\fIgroup_plugin\fR
+option in
+\fIsudoers\fR.
+If no arguments were given,
+\fIargv\fR
+will be
+\fRNULL\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+cleanup
+.nf
+.RS 6n
+void (*cleanup)();
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcleanup\fR()
+function is called when
+\fBsudoers\fR
+has finished its
+group checks.
+The plugin should free any memory it has allocated and close open file handles.
+.RE
+.TP 6n
+query
+.br
+.nf
+.RS 6n
+int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBquery\fR()
+function is used to ask the group plugin whether
+\fIuser\fR
+is a member of
+\fIgroup\fR.
+.sp
+The function arguments are as follows:
+.TP 6n
+user
+The name of the user being looked up in the external group database.
+.TP 6n
+group
+.br
+The name of the group being queried.
+.TP 6n
+pwd
+The password database entry for
+\fIuser\fR,
+if any.
+If
+\fIuser\fR
+is not
+present in the password database,
+\fIpwd\fR
+will be
+\fRNULL\fR.
+.PD 0
+.PP
+.RE
+.PD
+.PP
+\fIGroup API Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
+ GROUP_API_VERSION_MINOR)
+.RE
+.fi
+For getters and setters see the
+\fIPolicy plugin API\fR.
+.SH "PLUGIN API CHANGELOG"
+The following revisions have been made to the Sudo Plugin API.
+.TP 6n
+Version 1.0
+Initial API version.
+.TP 6n
+Version 1.1 (sudo 1.8.0)
+The I/O logging plugin's
+\fBopen\fR()
+function was modified to take the
+\fRcommand_info\fR
+list as an argument.
+.TP 6n
+Version 1.2 (sudo 1.8.5)
+The Policy and I/O logging plugins'
+\fBopen\fR()
+functions are now passed
+a list of plugin parameters if any are specified in
+sudo.conf(@mansectform@).
+.sp
+A simple hooks API has been introduced to allow plugins to hook in to the
+system's environment handling functions.
+.sp
+The
+\fRinit_session\fR
+Policy plugin function is now passed a pointer
+to the user environment which can be updated as needed.
+This can be used to merge in environment variables stored in the PAM
+handle before a command is run.
+.TP 6n
+Version 1.3 (sudo 1.8.7)
+Support for the
+\fIexec_background\fR
+entry has been added to the
+\fRcommand_info\fR
+list.
+.sp
+The
+\fImax_groups\fR
+and
+\fIplugin_dir\fR
+entries were added to the
+\fRsettings\fR
+list.
+.sp
+The
+\fBversion\fR()
+and
+\fBclose\fR()
+functions are now optional.
+Previously, a missing
+\fBversion\fR()
+or
+\fBclose\fR()
+function would result in a crash.
+If no policy plugin
+\fBclose\fR()
+function is defined, a default
+\fBclose\fR()
+function will be provided by the
+\fBsudo\fR
+front end that displays a warning if the command could not be
+executed.
+.sp
+The
+\fBsudo\fR
+front end now installs default signal handlers to trap common signals
+while the plugin functions are run.
+.TP 6n
+Version 1.4 (sudo 1.8.8)
+The
+\fIremote_host\fR
+entry was added to the
+\fRsettings\fR
+list.
+.TP 6n
+Version 1.5 (sudo 1.8.9)
+The
+\fIpreserve_fds\fR
+entry was added to the
+\fRcommand_info\fR
+list.
+.TP 6n
+Version 1.6 (sudo 1.8.11)
+The behavior when an I/O logging plugin returns an error
+(\-1)
+has changed.
+Previously, the
+\fBsudo\fR
+front end took no action when the
+\fBlog_ttyin\fR(),
+\fBlog_ttyout\fR(),
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR(),
+or
+\fBlog_stderr\fR()
+function returned an error.
+.sp
+The behavior when an I/O logging plugin returns 0 has changed.
+Previously, output from the command would be displayed to the
+terminal even if an output logging function returned 0.
+.TP 6n
+Version 1.7 (sudo 1.8.12)
+The
+\fIplugin_path\fR
+entry was added to the
+\fRsettings\fR
+list.
+.sp
+The
+\fIdebug_flags\fR
+entry now starts with a debug file path name and may occur multiple
+times if there are multiple plugin-specific Debug lines in the
+sudo.conf(@mansectform@) file.
+.TP 6n
+Version 1.8 (sudo 1.8.15)
+The
+\fIsudoedit_checkdir\fR
+and
+\fIsudoedit_follow\fR
+entries were added to the
+\fRcommand_info\fR
+list.
+The default value of
+\fIsudoedit_checkdir\fR
+was changed to true in sudo 1.8.16.
+.sp
+The sudo
+\fIconversation\fR
+function now takes a pointer to a
+\fRstruct sudo_conv_callback\fR
+as its fourth argument.
+The
+\fRsudo_conv_t\fR
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
+.TP 6n
+Version 1.9 (sudo 1.8.16)
+The
+\fIexecfd\fR
+entry was added to the
+\fRcommand_info\fR
+list.
+.TP 6n
+Version 1.10 (sudo 1.8.19)
+The
+\fIumask\fR
+entry was added to the
+\fRuser_info\fR
+list.
+The
+\fIiolog_group\fR,
+\fIiolog_mode\fR,
+and
+\fIiolog_user\fR
+entries were added to the
+\fRcommand_info\fR
+list.
+.TP 6n
+Version 1.11 (sudo 1.8.20)
+The
+\fItimeout\fR
+entry was added to the
+\fRsettings\fR
+list.
+.TP 6n
+Version 1.12 (sudo 1.8.21)
+The
+\fRchange_winsize\fR
+field was added to the io_plugin struct.
+.TP 6n
+Version 1.13 (sudo 1.8.26)
+The
+\fRlog_suspend\fR
+field was added to the io_plugin struct.
+.TP 6n
+Version 1.14 (sudo 1.8.29)
+The
+\fIumask_override\fR
+entry was added to the
+\fRcommand_info\fR
+list.
+.TP 6n
+Version 1.15 (sudo 1.9.0)
+The
+\fIcwd_optional\fR
+entry was added to the
+\fRcommand_info\fR
+list.
+.sp
+The
+\fIevent_alloc\fR
+field was added to the policy_plugin and io_plugin structs.
+.sp
+The
+\fIerrstr\fR
+argument was added to the policy and I/O plugin functions
+which the plugin function can use to return an error string.
+This string may be used by the audit plugin to report failure or
+error conditions set by the other plugins.
+.sp
+The
+\fBclose\fR()
+function is now is called regardless of whether or not a command
+was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+.sp
+\fRSUDO_CONV_REPL_MAX\fR
+has increased from 255 to 1023 bytes.
+.sp
+Support for audit and approval plugins was added.
+.TP 6n
+Version 1.16 (sudo 1.9.3)
+Initial resource limit values were added to the
+\fRuser_info\fR
+list.
+.sp
+The
+\fIcmnd_chroot\fR
+and
+\fIcmnd_cwd\fR
+enties were added to the
+\fRsettings\fR
+list.
+.TP 6n
+Version 1.17 (sudo 1.9.4)
+The
+\fIevent_alloc\fR
+field was added to the audit_plugin and approval_plugin structs.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in
new file mode 100644
index 0000000..feb265c
--- /dev/null
+++ b/doc/sudo_plugin.mdoc.in
@@ -0,0 +1,4553 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2020 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.
+.\"
+.Dd November 17, 2020
+.Dt SUDO_PLUGIN @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_plugin
+.Nd Sudo Plugin API
+.Sh DESCRIPTION
+Starting with version 1.8,
+.Nm sudo
+supports a plugin API
+for policy and session logging.
+Plugins may be compiled as dynamic shared objects (the default on
+systems that support them) or compiled statically into the
+.Nm sudo
+binary itself.
+By default, the
+.Nm sudoers
+policy plugin and an associated I/O logging plugin are used.
+Via the plugin API,
+.Nm sudo
+can be configured to use alternate policy and/or I/O logging plugins
+provided by third parties.
+The plugins to be used are specified in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+The API is versioned with a major and minor number.
+The minor version number is incremented when additions are made.
+The major number is incremented when incompatible changes are made.
+A plugin should be check the version passed to it and make sure that the
+major version matches.
+.Pp
+The plugin API is defined by the
+.Li sudo_plugin.h
+header file.
+.Ss Policy plugin API
+A policy plugin must declare and populate a
+.Li policy_plugin
+struct in the global scope.
+This structure contains pointers to the functions that implement the
+.Nm sudo
+policy checks.
+The name of the symbol should be specified in
+.Xr sudo.conf @mansectform@
+along with a path to the plugin so that
+.Nm sudo
+can load it.
+.Bd -literal
+struct policy_plugin {
+#define SUDO_POLICY_PLUGIN 1
+ 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 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);
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ 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);
+ int (*validate)(const char **errstr);
+ void (*invalidate)(int remove);
+ int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.Ed
+.Pp
+The policy_plugin struct has the following fields:
+.Bl -tag -width 4n
+.It type
+The
+.Li type
+field should always be set to SUDO_POLICY_PLUGIN.
+.It version
+The
+.Li version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+.Ed
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It conversation
+A pointer to the
+.Fn conversation
+function that can be used by the plugin to interact with the user (see
+.Sx Conversation API
+for details).
+Returns 0 on success and \-1 on failure.
+.It plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error messages (see
+.Sx Conversation API
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.It settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Em settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+The following values may be set by
+.Nm sudo :
+.Bl -tag -width 4n
+.It bsdauth_type=string
+Authentication type, if specified by the
+.Fl a
+option, to use on
+systems where
+.Bx
+authentication is supported.
+.It closefrom=number
+If specified, the user has requested via the
+.Fl C
+option that
+.Nm sudo
+close all files descriptors with a value of
+.Em number
+or higher.
+The plugin may optionally pass this, or another value, back in the
+.Em command_info
+list.
+.It cmnd_chroot=string
+The root directory (see
+.Xr chroot 2 )
+to run the command in, as specified by the user via the
+.Fl R
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+root directory.
+Only available starting with API version 1.16.
+.It cmnd_cwd=string
+The working directory to run the command in, as specified by the user via the
+.Fl D
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+working directory.
+Only available starting with API version 1.16.
+.It debug_flags=string
+A debug file path name followed by a space and a comma-separated
+list of debug flags that correspond to the plugin's
+.Li Debug
+entry in
+.Xr sudo.conf @mansectform@ ,
+if there is one.
+The flags are passed to the plugin exactly as they appear in
+.Xr sudo.conf @mansectform@ .
+The syntax used by
+.Nm sudo
+and the
+.Nm sudoers
+plugin is
+.Em subsystem Ns @ Ns Em priority
+but a plugin is free to use a different
+format so long as it does not include a comma
+.Pq Ql ,\& .
+Prior to
+.Nm sudo
+1.8.12, there was no way to specify plugin-specific
+.Em debug_flags
+so the value was always the same as that used by the
+.Nm sudo
+front end and did not include a path name, only the flags themselves.
+As of version 1.7 of the plugin interface,
+.Nm sudo
+will only pass
+.Em debug_flags
+if
+.Xr sudo.conf @mansectform@
+contains a plugin-specific
+.Li Debug
+entry.
+.It ignore_ticket=bool
+Set to true if the user specified the
+.Fl k
+option along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+.Em implied_shell
+to true.
+This allows
+.Nm sudo
+with no arguments
+to be used similarly to
+.Xr su 1 .
+If the plugin does not to support this usage, it may return a value of \-2
+from the
+.Fn check_policy
+function, which will cause
+.Nm sudo
+to print a usage message and
+exit.
+.It implied_shell=bool
+If the user does not specify a program on the command line,
+.Nm sudo
+will pass the plugin the path to the user's shell and set
+.It login_class=string
+.Bx
+login class to use when setting resource limits and nice value,
+if specified by the
+.Fl c
+option.
+.It login_shell=bool
+Set to true if the user specified the
+.Fl i
+option, indicating that
+the user wishes to run a login shell.
+.It max_groups=int
+The maximum number of groups a user may belong to.
+This will only be present if there is a corresponding setting in
+.Xr sudo.conf @mansectform@ .
+.It network_addrs=list
+A space-separated list of IP network addresses and netmasks in the
+form
+.Dq addr/netmask ,
+e.g.,
+.Dq 192.168.1.2/255.255.255.0 .
+The address and netmask pairs may be either IPv4 or IPv6, depending on
+what the operating system supports.
+If the address contains a colon
+.Pq Ql :\& ,
+it is an IPv6 address, else it is IPv4.
+.It noninteractive=bool
+Set to true if the user specified the
+.Fl n
+option, indicating that
+.Nm sudo
+should operate in non-interactive mode.
+The plugin may reject a command run in non-interactive mode if user
+interaction is required.
+.It plugin_dir=string
+The default plugin directory used by the
+.Nm sudo
+front end.
+This is the default directory set at compile time and may not
+correspond to the directory the running plugin was loaded from.
+It may be used by a plugin to locate support files.
+.It plugin_path=string
+The path name of plugin loaded by the
+.Nm sudo
+front end.
+The path name will be a fully-qualified unless the plugin was
+statically compiled into
+.Nm sudo .
+.It preserve_environment=bool
+Set to true if the user specified the
+.Fl E
+option, indicating that
+the user wishes to preserve the environment.
+.It preserve_groups=bool
+Set to true if the user specified the
+.Fl P
+option, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+.It progname=string
+The command name that sudo was run as, typically
+.Dq sudo
+or
+.Dq sudoedit .
+.It prompt=string
+The prompt to use when requesting a password, if specified via
+the
+.Fl p
+option.
+.It remote_host=string
+The name of the remote host to run the command on, if specified via
+the
+.Fl h
+option.
+Support for running the command on a remote host is meant to be implemented
+via a helper program that is executed in place of the user-specified command.
+The
+.Nm sudo
+front end is only capable of executing commands on the local host.
+Only available starting with API version 1.4.
+.It run_shell=bool
+Set to true if the user specified the
+.Fl s
+option, indicating that the user wishes to run a shell.
+.It runas_group=string
+The group name or gid to run the command as, if specified via
+the
+.Fl g
+option.
+.It runas_user=string
+The user name or uid to run the command as, if specified via the
+.Fl u
+option.
+.It selinux_role=string
+SELinux role to use when executing the command, if specified by
+the
+.Fl r
+option.
+.It selinux_type=string
+SELinux type to use when executing the command, if specified by
+the
+.Fl t
+option.
+.It set_home=bool
+Set to true if the user specified the
+.Fl H
+option.
+If true, set the
+.Li HOME
+environment variable to the target user's home directory.
+.It sudoedit=bool
+Set to true when the
+.Fl e
+option is specified or if invoked as
+.Nm sudoedit .
+The plugin shall substitute an editor into
+.Em argv
+in the
+.Fn check_policy
+function or return \-2 with a usage error
+if the plugin does not support
+.Em sudoedit .
+For more information, see the
+.Em check_policy
+section.
+.It timeout=string
+Command timeout specified by the user via the
+.Fl T
+option.
+Not all plugins support command timeouts and the ability of the
+user to set a timeout may be restricted by policy.
+The format of the timeout string is plugin-specific.
+.El
+.Pp
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+.It user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+The following values may be set by
+.Nm sudo :
+.Bl -tag -width 4n
+.It cols=int
+The number of columns the user's terminal supports.
+If there is no terminal device available, a default value of 80 is used.
+.It cwd=string
+The user's current working directory.
+.It egid=gid_t
+The effective group-ID of the user invoking
+.Nm sudo .
+.It euid=uid_t
+The effective user-ID of the user invoking
+.Nm sudo .
+.It gid=gid_t
+The real group-ID of the user invoking
+.Nm sudo .
+.It groups=list
+The user's supplementary group list formatted as a string of
+comma-separated group-IDs.
+.It host=string
+The local machine's hostname as returned by the
+.Xr gethostname 2
+system call.
+.It lines=int
+The number of lines the user's terminal supports.
+If there is
+no terminal device available, a default value of 24 is used.
+.It pgid=int
+The ID of the process group that the running
+.Nm sudo
+process is a member of.
+Only available starting with API version 1.2.
+.It pid=int
+The process ID of the running
+.Nm sudo
+process.
+Only available starting with API version 1.2.
+.It ppid=int
+The parent process ID of the running
+.Nm sudo
+process.
+Only available starting with API version 1.2.
+.It rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It sid=int
+The session ID of the running
+.Nm sudo
+process or 0 if
+.Nm sudo
+is not part of a POSIX job control session.
+Only available starting with API version 1.2.
+.It tcpgid=int
+The ID of the foreground process group associated with the terminal
+device associated with the
+.Nm sudo
+process or 0 if there is no terminal present.
+Only available starting with API version 1.2.
+.It tty=string
+The path to the user's terminal device.
+If the user has no terminal device associated with the session,
+the value will be empty, as in
+.Dq Li tty= .
+.It uid=uid_t
+The real user-ID of the user invoking
+.Nm sudo .
+.It umask=octal
+The invoking user's file creation mask.
+Only available starting with API version 1.10.
+.It user=string
+The name of the user invoking
+.Nm sudo .
+.El
+.It user_env
+The user's environment in the form of a
+.Dv NULL Ns -terminated vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em user_env ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It plugin_options
+Any (non-comment) strings immediately after the plugin path are
+passed as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were
+specified,
+.Em plugin_options
+will be the
+.Dv NULL
+pointer.
+.Pp
+NOTE: the
+.Em plugin_options
+parameter is only available starting with
+API version 1.2.
+A plugin
+.Sy must
+check the API version specified
+by the
+.Nm sudo
+front end before using
+.Em plugin_options .
+Failure to do so may result in a crash.
+.It errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It close
+.Bd -literal -compact
+void (*close)(int exit_status, int error);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+Starting with API version 1.15,
+.Fn close
+is called regardless of whether or not a command was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+It is not possible to tell whether a command was run based solely
+on the arguments passed to the
+.Fn close
+function.
+To determine if a command was actually run,
+the plugin must keep track of whether or not the
+.Fn check_policy
+function returned successfully.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It exit_status
+The command's exit status, as returned by the
+.Xr wait 2
+system call, or zero if no command was run.
+The value of
+.Li exit_status
+is undefined if
+.Li error
+is non-zero.
+.It error
+If the command could not be executed, this is set to the value of
+.Li errno
+set by the
+.Xr execve 2
+system call.
+The plugin is responsible for displaying error information via the
+.Fn conversation
+or
+.Fn plugin_printf
+function.
+If the command was successfully executed, the value of
+.Li error
+is zero.
+.El
+.Pp
+If no
+.Fn close
+function is defined, no I/O logging plugins are loaded,
+and neither the
+.Em timeout
+not
+.Em use_pty
+options are set in the
+.Li command_info
+list, the
+.Nm sudo
+front end may execute the command directly instead of running
+it as a child process.
+.It show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies
+the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the verbose flag will be set.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It check_policy
+.Bd -literal -compact
+int (*check_policy)(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **argv_out[], char **user_env_out[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn check_policy
+function is called by
+.Nm sudo
+to determine
+whether the user is allowed to run the specified commands.
+.Pp
+If the
+.Em sudoedit
+option was enabled in the
+.Em settings
+array
+passed to the
+.Fn open
+function, the user has requested
+.Em sudoedit
+mode.
+.Em sudoedit
+is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.
+.Nm sudo
+achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.
+If the plugin supports
+.Em sudoedit ,
+it should choose the editor to be used, potentially from a variable
+in the user's environment, such as
+.Li EDITOR ,
+and include it in
+.Em argv_out
+(note that environment
+variables may include command line options).
+The files to be edited should be copied from
+.Em argv
+into
+.Em argv_out ,
+separated from the
+editor and its arguments by a
+.Dq Li --
+element.
+The
+.Dq Li --
+will
+be removed by
+.Nm sudo
+before the editor is executed.
+The plugin should also set
+.Em sudoedit=true
+in the
+.Em command_info
+list.
+.Pp
+The
+.Fn check_policy
+function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if
+.Em sudoedit
+was specified but is unsupported by the plugin.
+In the latter case,
+.Nm sudo
+will print a usage message before it
+exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It argc
+The number of elements in
+.Em argv ,
+not counting the final
+.Dv NULL
+pointer.
+.It argv
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the
+.Xr execve 2
+system call.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.It env_add
+Additional environment variables specified by the user on the command
+line in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+.Pp
+When parsing
+.Em env_add ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It command_info
+Information about the command being run in the form of
+.Dq name=value
+strings.
+These values are used by
+.Nm sudo
+to set the execution
+environment when running a command.
+The plugin is responsible for creating and populating the vector,
+which must be terminated with a
+.Dv NULL
+pointer.
+The following values are recognized by
+.Nm sudo :
+.Bl -tag -width 4n
+.It chroot=string
+The root directory to use when running the command.
+.It closefrom=number
+If specified,
+.Nm sudo
+will close all files descriptors with a value
+of
+.Em number
+or higher.
+.It command=string
+Fully qualified path to the command to be executed.
+.It cwd=string
+The current working directory to change to when executing the command.
+If
+.Nm sudo
+is unable to change to the new working directory, the command will
+not be run unless
+.Em cwd_optional
+is also set (see below).
+.It cwd_optional=bool
+If enabled,
+.Nm sudo
+will treat an inability to change to the new working directory as a
+non-fatal error.
+This setting has no effect unless
+.Em cwd
+is also set.
+.It exec_background=bool
+By default,
+.Nm sudo
+runs a command as the foreground process as long as
+.Nm sudo
+itself is running in the foreground.
+When
+.Em exec_background
+is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+.Em use_pty
+setting), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+.Dv SIGTTIN
+signal (or
+.Dv SIGTTOU
+in the case of terminal settings).
+If this happens when
+.Nm sudo
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+.Nm sudo
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+.Em sudo
+behavior or when the command is not being run in a pseudo-terminal.
+.Pp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+.Fn tcgetattr
+and
+.Fn tcsetattr
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+.Dv SIGTTIN
+or
+.Dv SIGTTOU
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+.Dv SIGTOP )
+will not be automatically foregrounded.
+Some versions of the linux
+.Xr su 1
+command behave this way.
+Because of this, a plugin should not set
+.Em exec_background
+unless it is explicitly enabled by the administrator and there should
+be a way to enabled or disable it on a per-command basis.
+.Pp
+This setting has no effect unless I/O logging is enabled or
+.Em use_pty
+is enabled.
+.It execfd=number
+If specified,
+.Nm sudo
+will use the
+.Xr fexecve 2
+system call to execute the command instead of
+.Xr execve 2 .
+The specified
+.Em number
+must refer to an open file descriptor.
+.It iolog_compress=bool
+Set to true if the I/O logging plugins, if any, should compress the
+log data.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_group=string
+The group that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_mode=octal
+The file permission mode to use when creating I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_user=string
+The user that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_path=string
+Fully qualified path to the file or directory in which I/O log is
+to be stored.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+If no I/O logging plugin is loaded, this setting has no effect.
+.It iolog_stdin=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_stdout=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_stderr=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_ttyin=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.
+This only includes input typed by the user and not from a pipe or
+redirected from a file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_ttyout=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.
+This only includes output to the screen, not output to a pipe or file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It login_class=string
+.Bx
+login class to use when setting resource limits and nice value (optional).
+This option is only set on systems that support login classes.
+.It nice=int
+Nice value (priority) to use when executing the command.
+The nice value, if specified, overrides the priority associated with the
+.Em login_class
+on
+.Bx
+systems.
+.It noexec=bool
+If set, prevent the command from executing other programs.
+.It preserve_fds=list
+A comma-separated list of file descriptors that should be
+preserved, regardless of the value of the
+.Em closefrom
+setting.
+Only available starting with API version 1.5.
+.It preserve_groups=bool
+If set,
+.Nm sudo
+will preserve the user's group vector instead of
+initializing the group vector based on
+.Li runas_user .
+.It runas_egid=gid
+Effective group-ID to run the command as.
+If not specified, the value of
+.Em runas_gid
+is used.
+.It runas_euid=uid
+Effective user-ID to run the command as.
+If not specified, the value of
+.Em runas_uid
+is used.
+.It runas_gid=gid
+Group-ID to run the command as.
+.It runas_group=string
+The name of the group the command will run as, if it is different
+from the
+.Em runas_user Ns 's
+default group.
+This value is provided for auditing purposes only, the
+.Nm sudo
+front-end uses
+.Em runas_egid
+and
+.Em runas_gid
+when executing the command.
+.It runas_groups=list
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group-IDs.
+If
+.Em preserve_groups
+is set, this option is ignored.
+.It runas_uid=uid
+User-ID to run the command as.
+.It runas_user=string
+The name of the user the command will run as, which should correspond to
+.Em runas_euid
+(or
+.Em runas_uid
+if
+.Em runas_euid
+is not set).
+This value is provided for auditing purposes only, the
+.Nm sudo
+front-end uses
+.Em runas_euid
+and
+.Em runas_uid
+when executing the command.
+.It selinux_role=string
+SELinux role to use when executing the command.
+.It selinux_type=string
+SELinux type to use when executing the command.
+.It set_utmp=bool
+Create a utmp (or utmpx) entry when a pseudo-terminal is allocated.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+.It sudoedit=bool
+Set to true when in
+.Em sudoedit
+mode.
+The plugin may enable
+.Em sudoedit
+mode even if
+.Nm sudo
+was not invoked as
+.Nm sudoedit .
+This allows the plugin to perform command substitution and transparently
+enable
+.Em sudoedit
+when the user attempts to run an editor.
+.It sudoedit_checkdir=bool
+Set to false to disable directory writability checks in
+.Nm sudoedit .
+By default,
+.Nm sudoedit
+1.8.16 and higher will check all directory components of the path to be
+edited for writability by the invoking user.
+Symbolic links will not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+.Nm sudoedit
+is run by root.
+The
+.Em sudoedit_follow
+option can be set to false to disable this check.
+Only available starting with API version 1.8.
+.It sudoedit_follow=bool
+Set to true to allow
+.Nm sudoedit
+to edit files that are symbolic links.
+By default,
+.Nm sudoedit
+1.8.15 and higher will refuse to open a symbolic link.
+The
+.Em sudoedit_follow
+option can be used to restore the older behavior and allow
+.Nm sudoedit
+to open symbolic links.
+Only available starting with API version 1.8.
+.It timeout=int
+Command timeout.
+If non-zero then when the timeout expires the command will be killed.
+.It umask=octal
+The file creation mask to use when executing the command.
+This value may be overridden by PAM or login.conf on some systems
+unless the
+.Em umask_override
+option is also set.
+.It umask_override=bool
+Force the value specified by the
+.Em umask
+option to override any umask set by PAM or login.conf.
+.It use_pty=bool
+Allocate a pseudo-terminal to run the command in, regardless of whether
+or not I/O logging is in use.
+By default,
+.Nm sudo
+will only run
+the command in a pseudo-terminal when an I/O log plugin is loaded.
+.It utmp_user=string
+User name to use when constructing a new utmp (or utmpx) entry when
+.Em set_utmp
+is enabled.
+This option can be used to set the user field in the utmp entry to
+the user the command runs as rather than the invoking user.
+If not set,
+.Nm sudo
+will base the new entry on
+the invoking user's existing entry.
+.El
+.Pp
+Unsupported values will be ignored.
+.It argv_out
+The
+.Dv NULL Ns -terminated
+argument vector to pass to the
+.Xr execve 2
+system call when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.It user_env_out
+The
+.Dv NULL Ns -terminated
+environment vector to use when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.It errstr
+If the
+.Fn check_policy
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It list
+.Bd -literal -compact
+int (*list)(int argc, char * const argv[], int verbose,
+ const char *list_user, const char **errstr);
+.Ed
+.Pp
+List available privileges for the invoking user.
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to
+the user.
+.Pp
+Privileges should be output via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It argc
+The number of elements in
+.Em argv ,
+not counting the final
+.Dv NULL
+pointer.
+.It argv
+If
+.No non- Ns Dv NULL ,
+an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the
+.Xr execve 2
+system call.
+If the command is permitted by the policy, the fully-qualified path
+to the command should be displayed along with any command line arguments.
+.It verbose
+Flag indicating whether to list in verbose mode or not.
+.It list_user
+The name of a different user to list privileges for if the policy
+allows it.
+If
+.Dv NULL ,
+the plugin should list the privileges of the invoking user.
+.It errstr
+If the
+.Fn list
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It validate
+.Bd -literal -compact
+int (*validate)(const char **errstr);
+.Ed
+.Pp
+The
+.Fn validate
+function is called when
+.Nm sudo
+is run with the
+.Fl v
+option.
+For policy plugins such as
+.Nm sudoers
+that cache
+authentication credentials, this function will validate and cache
+the credentials.
+.Pp
+The
+.Fn validate
+function should be
+.Dv NULL
+if the plugin does not support credential caching.
+.Pp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional
+error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It errstr
+If the
+.Fn validate
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It invalidate
+.Bd -literal -compact
+void (*invalidate)(int remove);
+.Ed
+.Pp
+The
+.Fn invalidate
+function is called when
+.Nm sudo
+is run with the
+.Fl k
+or
+.Fl K
+option.
+For policy plugins such as
+.Nm sudoers
+that
+cache authentication credentials, this function will invalidate the
+credentials.
+If the
+.Em remove
+flag is set, the plugin may remove
+the credentials instead of simply invalidating them.
+.Pp
+The
+.Fn invalidate
+function should be
+.Dv NULL
+if the plugin does not support credential caching.
+.It init_session
+.Bd -literal -compact
+int (*init_session)(struct passwd *pwd, char **user_env_out[]);
+.Ed
+.Pp
+The
+.Fn init_session
+function is called before
+.Nm sudo
+sets up the
+execution environment for the command.
+It is run in the parent
+.Nm sudo
+process and before any uid or gid changes.
+This can be used to perform session setup that is not supported by
+.Em command_info ,
+such as opening the PAM session.
+The
+.Fn close
+function can be
+used to tear down the session that was opened by
+.Li init_session .
+.Pp
+The
+.Em pwd
+argument points to a passwd struct for the user the
+command will be run as if the uid the command will run as was found
+in the password database, otherwise it will be
+.Dv NULL .
+.Pp
+The
+.Em user_env_out
+argument points to the environment the command will
+run in, in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+This is the same string passed back to the front end via
+the Policy Plugin's
+.Em user_env_out
+parameter.
+If the
+.Fn init_session
+function needs to modify the user environment, it should update the
+pointer stored in
+.Em user_env_out .
+The expected use case is to merge the contents of the PAM environment
+(if any) with the contents of
+.Em user_env_out .
+NOTE: the
+.Em user_env_out
+parameter is only available
+starting with API version 1.2.
+A plugin
+.Sy must
+check the API
+version specified by the
+.Nm sudo
+front end before using
+.Em user_env_out .
+Failure to do so may result in a crash.
+.Pp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional
+error information to the user.
+.It register_hooks
+.Bd -literal -compact
+void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+.Ed
+.Pp
+The
+.Fn register_hooks
+function is called by the sudo front end to
+register any hooks the plugin needs.
+If the plugin does not support hooks,
+.Li register_hooks
+should be set to the
+.Dv NULL
+pointer.
+.Pp
+The
+.Em version
+argument describes the version of the hooks API
+supported by the
+.Nm sudo
+front end.
+.Pp
+The
+.Fn register_hook
+function should be used to register any supported
+hooks the plugin needs.
+It returns 0 on success, 1 if the hook type is not supported and \-1
+if the major version in
+.Li struct hook
+does not match the front end's major hook API version.
+.Pp
+See the
+.Sx Hook function API
+section below for more information
+about hooks.
+.Pp
+NOTE: the
+.Fn register_hooks
+function is only available starting
+with API version 1.2.
+If the
+.Nm sudo
+front end doesn't support API
+version 1.2 or higher,
+.Li register_hooks
+will not be called.
+.It deregister_hooks
+.Bd -literal -compact
+void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+.Ed
+.Pp
+The
+.Fn deregister_hooks
+function is called by the sudo front end
+to deregister any hooks the plugin has registered.
+If the plugin does not support hooks,
+.Li deregister_hooks
+should be set to the
+.Dv NULL
+pointer.
+.Pp
+The
+.Em version
+argument describes the version of the hooks API
+supported by the
+.Nm sudo
+front end.
+.Pp
+The
+.Fn deregister_hook
+function should be used to deregister any
+hooks that were put in place by the
+.Fn register_hook
+function.
+If the plugin tries to deregister a hook that the front end does not support,
+.Li deregister_hook
+will return an error.
+.Pp
+See the
+.Sx Hook function API
+section below for more information
+about hooks.
+.Pp
+NOTE: the
+.Fn deregister_hooks
+function is only available starting
+with API version 1.2.
+If the
+.Nm sudo
+front end doesn't support API
+version 1.2 or higher,
+.Li deregister_hooks
+will not be called.
+.It event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Li struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fn event_alloc
+pointer is filled in by the
+.Nm sudo
+front end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+NOTE: the
+.Fn event_alloc
+function is only available starting
+with API version 1.15.
+If the
+.Nm sudo
+front end doesn't support API
+version 1.15 or higher,
+.Fn event_alloc
+will not be set.
+.It errstr
+If the
+.Fn init_session
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.Pp
+.Em Policy Plugin Version Macros
+.Bd -literal
+/* Plugin API version major/minor. */
+#define SUDO_API_VERSION_MAJOR 1
+#define SUDO_API_VERSION_MINOR 13
+#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
+ SUDO_API_VERSION_MINOR)
+
+/* Getters and setters for API version */
+#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+} while(0)
+#define SUDO_API_VERSION_SET_MINOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0xffff0000) | (n); \e
+} while(0)
+.Ed
+.Ss I/O plugin API
+.Bd -literal
+struct io_plugin {
+#define SUDO_IO_PLUGIN 2
+ 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 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);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+ int (*log_suspend)(int signo, const char **errstr);
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.Ed
+.Pp
+When an I/O plugin is loaded,
+.Nm sudo
+runs the command in a pseudo-terminal.
+This makes it possible to log the input and output from the user's
+session.
+If any of the standard input, standard output or standard error do not
+correspond to a tty,
+.Nm sudo
+will open a pipe to capture
+the I/O for logging before passing it on.
+.Pp
+The log_ttyin function receives the raw user input from the terminal
+device (note that this will include input even when echo is disabled,
+such as when a password is read).
+The log_ttyout function receives output from the pseudo-terminal that is
+suitable for replaying the user's session at a later time.
+The
+.Fn log_stdin ,
+.Fn log_stdout
+and
+.Fn log_stderr
+functions are only called if the standard input, standard output
+or standard error respectively correspond to something other than
+a tty.
+.Pp
+Any of the logging functions may be set to the
+.Dv NULL
+pointer if no logging is to be performed.
+If the open function returns 0, no I/O will be sent to the plugin.
+.Pp
+If a logging function returns an error
+.Pq \-1 ,
+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
+If an input logging function rejects the data by returning 0, the
+command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning 0, 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.
+.Pp
+The audit_plugin struct has the following fields:
+.Bl -tag -width 4n
+.It type
+The
+.Li type
+field should always be set to
+.Dv SUDO_IO_PLUGIN .
+.It version
+The
+.Li version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t 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[]);
+.Ed
+.Pp
+The
+.Fn open
+function is run before the
+.Fn log_ttyin ,
+.Fn log_ttyout ,
+.Fn log_stdin ,
+.Fn log_stdout ,
+.Fn log_stderr ,
+.Fn log_suspend ,
+.Fn change_winsize ,
+or
+.Fn show_version
+functions are called.
+It is only called if the version is being requested or if the
+policy plugin's
+.Fn check_policy
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It conversation
+A pointer to the
+.Fn conversation
+function that may be used by the
+.Fn show_version
+function to display version information (see
+.Fn show_version
+below).
+The
+.Fn conversation
+function may also be used to display additional error message to the user.
+The
+.Fn conversation
+function returns 0 on success and \-1 on failure.
+.It plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used by the
+.Fn show_version
+function to display version information (see
+show_version below).
+The
+.Fn plugin_printf
+function may also be used to display additional error message to the user.
+The
+.Fn plugin_printf
+function returns number of characters printed on success and \-1 on failure.
+.It settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Em settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It command_info
+A vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It argc
+The number of elements in
+.Em argv ,
+not counting the final
+.Dv NULL
+pointer.
+It can be zero, when
+.Nm sudo
+is called with
+.Fl V .
+.It argv
+If
+.No non- Ns Dv NULL ,
+an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+.Xr execve 2
+system call.
+.It user_env
+The user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em user_env ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Em plugin_options
+will be the
+.Dv NULL
+pointer.
+.Pp
+NOTE: the
+.Em plugin_options
+parameter is only available starting with
+API version 1.2.
+A plugin
+.Sy must
+check the API version specified
+by the
+.Nm sudo
+front end before using
+.Em plugin_options .
+Failure to do so may result in a crash.
+.It errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It close
+.Bd -literal -compact
+void (*close)(int exit_status, int error);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It exit_status
+The command's exit status, as returned by the
+.Xr wait 2
+system call, or zero if no command was run.
+The value of
+.Li exit_status
+is undefined if
+.Li error
+is non-zero.
+.It error
+If the command could not be executed, this is set to the value of
+.Li errno
+set by the
+.Xr execve 2
+system call.
+If the command was successfully executed, the value of
+.Li error
+is zero.
+.El
+.It show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies
+the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It log_ttyin
+.Bd -literal -compact
+int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_ttyin
+function is called whenever data can be read from
+the user but before it is passed to the running command.
+This allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data
+is rejected (which will terminate the running command) or \-1 if an
+error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It buf
+The buffer containing user input.
+.It len
+The length of
+.Em buf
+in bytes.
+.It errstr
+If the
+.Fn log_ttyin
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It log_ttyout
+.Bd -literal -compact
+int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_ttyout
+function is called whenever data can be read from
+the command but before it is written to the user's terminal.
+This allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is rejected
+(which will terminate the running command) or \-1 if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It buf
+The buffer containing command output.
+.It len
+The length of
+.Em buf
+in bytes.
+.It errstr
+If the
+.Fn log_ttyout
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It log_stdin
+.Bd -literal -compact
+int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stdin
+function is only used if the standard input does
+not correspond to a tty device.
+It is called whenever data can be read from the standard input but
+before it is passed to the running command.
+This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It buf
+The buffer containing user input.
+.It len
+The length of
+.Em buf
+in bytes.
+.It errstr
+If the
+.Fn log_stdin
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It log_stdout
+.Bd -literal -compact
+int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stdout
+function is only used if the standard output does not correspond
+to a tty device.
+It is called whenever data can be read from the command but before
+it is written to the standard output.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It buf
+The buffer containing command output.
+.It len
+The length of
+.Em buf
+in bytes.
+.It errstr
+If the
+.Fn log_stdout
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It log_stderr
+.Bd -literal -compact
+int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stderr
+function is only used if the standard error does
+not correspond to a tty device.
+It is called whenever data can be read from the command but before it
+is written to the standard error.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is
+rejected (which will terminate the running command) or \-1 if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It buf
+The buffer containing command output.
+.It len
+The length of
+.Em buf
+in bytes.
+.It errstr
+If the
+.Fn log_stderr
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It register_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Li register_hooks .
+.It deregister_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Li deregister_hooks .
+.It change_winsize
+.Bd -literal -compact
+int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn change_winsize
+function is called whenever the window size of the terminal changes from
+the initial values specified in the
+.Li user_info
+list.
+Returns \-1 if an error occurred, in which case no further calls to
+.Fn change_winsize
+will be made,
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It lines
+The number of lines (rows) in the re-sized terminal.
+.It cols
+The number of columns in the re-sized terminal.
+.It errstr
+If the
+.Fn change_winsize
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It log_suspend
+.Bd -literal -compact
+int (*log_suspend)(int signo, const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_suspend
+function is called whenever a command is suspended or resumed.
+Logging this information makes it possible to skip the period of time when
+the command was suspended during playback of a session.
+Returns \-1 if an error occurred, in which case no further calls to
+.Fn log_suspend
+will be made,
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It signo
+The signal that caused the command to be suspended, or
+.Dv SIGCONT
+if the command was resumed.
+.It errstr
+If the
+.Fn log_suspend
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+NOTE: the
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.It event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Li struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fn event_alloc
+pointer is filled in by the
+.Nm sudo
+front end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+NOTE: the
+.Fn event_alloc
+function is only available starting
+with API version 1.15.
+If the
+.Nm sudo
+front end doesn't support API
+version 1.15 or higher,
+.Fn event_alloc
+will not be set.
+.El
+.Pp
+.Em I/O Plugin Version Macros
+.Pp
+Same as for the
+.Sx Policy plugin API .
+.El
+.Ss Audit plugin API
+.Bd -literal
+/* Audit plugin close function status types. */
+#define SUDO_PLUGIN_NO_STATUS 0
+#define SUDO_PLUGIN_WAIT_STATUS 1
+#define SUDO_PLUGIN_EXEC_ERROR 2
+#define SUDO_PLUGIN_SUDO_ERROR 3
+
+#define SUDO_AUDIT_PLUGIN 3
+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[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int status_type, int status);
+ int (*accept)(const char *plugin_name,
+ unsigned int plugin_type, char * const command_info[],
+ char * const run_argv[], char * const run_envp[],
+ const char **errstr);
+ int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*show_version)(int verbose);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+}
+.Ed
+.Pp
+An audit plugin can be used to log successful and unsuccessful attempts
+to run
+.Nm sudo
+independent of the policy or any I/O plugins.
+Multiple audit plugins may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+The audit_plugin struct has the following fields:
+.Bl -tag -width 4n
+.It type
+The
+.Li type
+field should always be set to
+.Dv SUDO_AUDIT_PLUGIN .
+.It version
+The
+.Li version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_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);
+.Ed
+.Pp
+The audit
+.Fn open
+function is run before any other
+.Nm sudo
+plugin API functions.
+This makes it possible to audit failures in the other plugins.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It conversation
+A pointer to the
+.Fn conversation
+function that may be used by the
+.Fn show_version
+function to display version information (see
+.Fn show_version
+below).
+The
+.Fn conversation
+function may also be used to display additional error message to the user.
+The
+.Fn conversation
+function returns 0 on success and \-1 on failure.
+.It plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used by the
+.Fn show_version
+function to display version information (see
+show_version below).
+The
+.Fn plugin_printf
+function may also be used to display additional error message to the user.
+The
+.Fn plugin_printf
+function returns number of characters printed on success and \-1 on failure.
+.It settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Em settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+If
+.Fa submit_argv
+only consists of options, which may be the case with the
+.Fl l
+or
+.Fl v
+options,
+.Li submit_argv[submit_optind]
+will evaluate to the NULL pointer.
+.It submit_argv
+The argument vector
+.Nm sudo
+was invoked with, including all command line options.
+The
+.Fa submit_optind
+argument can be used to determine the end of the command line options.
+.It submit_envp
+The invoking user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em submit_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Em plugin_options
+will be the
+.Dv NULL
+pointer.
+.It errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It close
+.Bd -literal -compact
+void (*close)(int status_type, int status);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It status_type
+The type of status being passed.
+One of
+.Dv SUDO_PLUGIN_NO_STATUS ,
+.Dv SUDO_PLUGIN_WAIT_STATUS ,
+.Dv SUDO_PLUGIN_EXEC_ERROR
+or
+.Dv SUDO_PLUGIN_SUDO_ERROR .
+.It status
+Depending on the value of
+.Fa status_type ,
+this value is either
+ignored, the command's exit status as returned by the
+.Xr wait 2
+system call, the value of
+.Li errno
+set by the
+.Xr execve 2
+system call, or the value of
+.Li errno
+resulting from an error in the
+.Nm sudo
+front end.
+.El
+.It accept
+.Bd -literal -compact
+int (*accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.Ed
+.Pp
+The
+.Fn accept
+function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that accepted the command or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that accepted the command, currently either
+.Dv SUDO_POLICY_PLUGIN ,
+.Dv SUDO_POLICY_APPROVAL
+or
+.Dv SUDO_FRONT_END .
+The
+.Fn accept
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+.Fa command_info
+may include information from an I/O logging plugin as well.
+.Pp
+Typically, an audit plugin is interested in either the accept status from
+the
+.Nm sudo
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+.Fn accept
+and
+.Fn reject
+functions will
+.Em both
+be called.
+.It command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It run_argv
+A
+.Dv NULL Ns -terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+.Xr execve 2
+system call.
+.It run_envp
+The environment the command will be run with in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em run_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It errstr
+If the
+.Fn accept
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It reject
+.Bd -literal -compact
+int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn reject
+function is called when a command or action is rejected by a plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that rejected the command.
+.It plugin_type
+The type of plugin that rejected the command, currently either
+.Dv SUDO_POLICY_PLUGIN ,
+.Dv SUDO_APPROVAL_PLUGIN
+or
+.Dv SUDO_IO_PLUGIN .
+.Pp
+Unlike the
+.Fn accept
+function, the
+.Fn reject
+function is not called on behalf of the
+.Nm sudo
+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,
+.Fa audit_msg
+will be the
+.Dv NULL
+pointer.
+.It command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It errstr
+If the
+.Fn reject
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It error
+.Bd -literal -compact
+int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn error
+function is called when a plugin or the
+.Nm sudo
+front-end returns an error.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that generated the error or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that generated the error, or
+.Dv SUDO_FRONT_END
+for the
+.Nm sudo
+front-end.
+.It audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description,
+.Fa audit_msg
+will be the
+.Dv NULL
+pointer.
+.It command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It errstr
+If the
+.Fn error
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies
+the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the verbose flag will be set.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It register_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Li register_hooks .
+.It deregister_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Li deregister_hooks .
+.It event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Li struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fn event_alloc
+pointer is filled in by the
+.Nm sudo
+front end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+NOTE: the
+.Fn event_alloc
+function is only available starting
+with API version 1.17.
+If the
+.Nm sudo
+front end doesn't support API
+version 1.17 or higher,
+.Fn event_alloc
+will not be set.
+.El
+.Ss Approval plugin API
+.Bd -literal
+struct approval_plugin {
+#define SUDO_APPROVAL_PLUGIN 4
+ 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[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(void);
+ int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*show_version)(int verbose);
+};
+.Ed
+.Pp
+An approval plugin can be used to apply extra constraints after a
+command has been accepted by the policy plugin.
+Unlike the other plugin types, it does not remain open until the command
+completes.
+The plugin is opened before a call to
+.Fn check
+or
+.Fn show_version
+and closed shortly thereafter (audit plugin functions must be called
+before the plugin is closed).
+Multiple approval plugins may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+The approval_plugin struct has the following fields:
+.Bl -tag -width 4n
+.It type
+The
+.Li type
+field should always be set to
+.Dv SUDO_APPROVAL_PLUGIN .
+.It version
+The
+.Li version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_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);
+.Ed
+.Pp
+The approval
+.Fn open
+function is run immediately before a call to the plugin's
+.Fn check
+or
+.Fn show_version
+functions.
+It is only called if the version is being requested or if the
+policy plugin's
+.Fn check_policy
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It conversation
+A pointer to the
+.Fn conversation
+function that can be used by the plugin to interact with the user (see
+.Sx Conversation API
+for details).
+Returns 0 on success and \-1 on failure.
+.It plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error messages (see
+.Sx Conversation API
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.It settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Em settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+If
+.Fa submit_argv
+only consists of options, which may be the case with the
+.Fl l
+or
+.Fl v
+options,
+.Li submit_argv[submit_optind]
+will evaluate to the NULL pointer.
+.It submit_argv
+The argument vector
+.Nm sudo
+was invoked with, including all command line options.
+The
+.Fa submit_optind
+argument can be used to determine the end of the command line options.
+.It submit_envp
+The invoking user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em submit_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Em plugin_options
+will be the
+.Dv NULL
+pointer.
+.It errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It close
+.Bd -literal -compact
+void (*close)(void);
+.Ed
+.Pp
+The
+.Fn close
+function is called after the approval plugin's
+.Fn check
+or
+.Fn show_version
+functions have been called.
+It takes no arguments.
+The
+.Fn close
+function is typically used to perform plugin-specific cleanup,
+such as the freeing of memory objects allocated by the plugin.
+If the plugin does not need to perform any cleanup,
+.Fn close
+may be set to the
+.Dv NULL
+pointer.
+.It check
+.Bd -literal -compact
+int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.Ed
+.Pp
+The approval
+.Fn check
+function is run after the policy plugin
+.Fn check_policy
+function and before any I/O logging plugins.
+If multiple approval plugins are loaded, they must all succeed for
+the command to be allowed.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It command_info
+A vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Em command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It run_argv
+A
+.Dv NULL Ns -terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+.Xr execve 2
+system call.
+.It run_envp
+The environment the command will be run with in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Em run_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies
+the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the verbose flag will be set.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.El
+.Ss Signal handlers
+The
+.Nm sudo
+front end installs default signal handlers to trap common signals
+while the plugin functions are run.
+The following signals are trapped by default before the command is
+executed:
+.Pp
+.Bl -bullet -compact -width 1n
+.It
+.Dv SIGALRM
+.It
+.Dv SIGHUP
+.It
+.Dv SIGINT
+.It
+.Dv SIGPIPE
+.It
+.Dv SIGQUIT
+.It
+.Dv SIGTERM
+.It
+.Dv SIGTSTP
+.It
+.Dv SIGUSR1
+.It
+.Dv SIGUSR2
+.El
+.Pp
+If a fatal signal is received before the command is executed,
+.Nm sudo
+will call the plugin's
+.Fn close
+function with an exit status of 128 plus the value of the signal
+that was received.
+This allows for consistent logging of commands killed by a signal
+for plugins that log such information in their
+.Fn close
+function.
+An exception to this is
+.Ev SIGPIPE ,
+which is ignored until the command is executed.
+.Pp
+A plugin may temporarily install its own signal handlers but must
+restore the original handler before the plugin function returns.
+.Ss Hook function API
+Beginning with plugin API version 1.2, it is possible to install
+hooks for certain functions called by the
+.Nm sudo
+front end.
+.Pp
+Currently, the only supported hooks relate to the handling of
+environment variables.
+Hooks can be used to intercept attempts to get, set, or remove
+environment variables so that these changes can be reflected in
+the version of the environment that is used to execute a command.
+A future version of the API will support hooking internal
+.Nm sudo
+front end functions as well.
+.Pp
+.Em Hook structure
+.Pp
+Hooks in
+.Nm sudo
+are described by the following structure:
+.Bd -literal
+typedef int (*sudo_hook_fn_t)();
+
+struct sudo_hook {
+ unsigned int hook_version;
+ unsigned int hook_type;
+ sudo_hook_fn_t hook_fn;
+ void *closure;
+};
+.Ed
+.Pp
+The
+.Li sudo_hook
+structure has the following fields:
+.Bl -tag -width 4n
+.It hook_version
+The
+.Li hook_version
+field should be set to
+.Dv SUDO_HOOK_VERSION .
+.It hook_type
+The
+.Li hook_type
+field may be one of the following supported hook types:
+.Bl -tag -width 4n
+.It Dv SUDO_HOOK_SETENV
+The C library
+.Xr setenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Li hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_setenv_t)(const char *name,
+ const char *value, int overwrite, void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.It Dv SUDO_HOOK_UNSETENV
+The C library
+.Xr unsetenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Li hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
+ void *closure);
+.Ed
+.It Dv SUDO_HOOK_GETENV
+The C library
+.Xr getenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Li hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_getenv_t)(const char *name,
+ char **value, void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.It Dv SUDO_HOOK_PUTENV
+The C library
+.Xr putenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Li hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_putenv_t)(char *string,
+ void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.El
+.It hook_fn
+sudo_hook_fn_t hook_fn;
+.Pp
+The
+.Li hook_fn
+field should be set to the plugin's hook implementation.
+The actual function arguments will vary depending on the
+.Li hook_type
+(see
+.Li hook_type
+above).
+In all cases, the
+.Li closure
+field of
+.Li struct sudo_hook
+is passed as the last function parameter.
+This can be used to pass arbitrary data to the plugin's hook implementation.
+.Pp
+The function return value may be one of the following:
+.Bl -tag -width 4n
+.It Dv SUDO_HOOK_RET_ERROR
+The hook function encountered an error.
+.It Dv SUDO_HOOK_RET_NEXT
+The hook completed without error, go on to the next hook (including
+the system implementation if applicable).
+For example, a
+.Xr getenv 3
+hook might return
+.Dv SUDO_HOOK_RET_NEXT
+if the specified variable was not found in the private copy of the environment.
+.It Dv SUDO_HOOK_RET_STOP
+The hook completed without error, stop processing hooks for this invocation.
+This can be used to replace the system implementation.
+For example, a
+.Li setenv
+hook that operates on a private copy of
+the environment but leaves
+.Li environ
+unchanged.
+.El
+.El
+.Pp
+Note that it is very easy to create an infinite loop when hooking
+C library functions.
+For example, a
+.Xr getenv 3
+hook that calls the
+.Xr snprintf 3
+function may create a loop if the
+.Xr snprintf 3
+implementation calls
+.Xr getenv 3
+to check the locale.
+To prevent this, you may wish to use a static variable in the hook
+function to guard against nested calls.
+For example:
+.Bd -literal
+static int in_progress = 0; /* avoid recursion */
+if (in_progress)
+ return SUDO_HOOK_RET_NEXT;
+in_progress = 1;
+\&...
+in_progress = 0;
+return SUDO_HOOK_RET_STOP;
+.Ed
+.Pp
+.Em Hook API Version Macros
+.Bd -literal
+/* Hook API version major/minor */
+#define SUDO_HOOK_VERSION_MAJOR 1
+#define SUDO_HOOK_VERSION_MINOR 0
+#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
+ SUDO_HOOK_VERSION_MINOR)
+.Ed
+.Pp
+For getters and setters see the
+.Sx Policy plugin API .
+.Ss Event API
+When
+.Nm sudo
+runs a command, it uses an event loop to service signals and I/O.
+Events may be triggered based on time, a file or socket descriptor
+becoming ready, or due to receipt of a signal.
+Starting with API version 1.15, it is possible for a plugin to
+participate in this event loop by calling the
+.Fn event_alloc
+function.
+.Pp
+.Em Event structure
+.Pp
+Events are described by the following structure:
+.Pp
+.Bd -literal -compact
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure);
+
+struct sudo_plugin_event {
+ int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+ int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+ int (*del)(struct sudo_plugin_event *pev);
+ int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+ int (*fd)(struct sudo_plugin_event *pev);
+ void (*setbase)(struct sudo_plugin_event *pev, void *base);
+ void (*loopbreak)(struct sudo_plugin_event *pev);
+ void (*free)(struct sudo_plugin_event *pev);
+};
+.Ed
+.Pp
+The sudo_plugin_event struct contains the following function pointers:
+.Bl -tag -width 4n
+.It Fn set
+.Bd -literal -compact
+int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+.Ed
+.Pp
+The
+.Fn set
+function takes the following arguments:
+.Bl -tag -width 4n
+.It struct sudo_plugin_event * Ns Fa pev
+A pointer to the struct sudo_plugin_event itself.
+.It Fa fd
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+For time-based events,
+.Fa fd
+must be -1.
+.It Fa events
+The following values determine what will trigger the event callback:
+.Bl -tag -width 4n
+.It SUDO_PLUGIN_EV_TIMEOUT
+callback is run after the specified timeout expires
+.It SUDO_PLUGIN_EV_READ
+callback is run when the file descriptor is readable
+.It SUDO_PLUGIN_EV_WRITE
+callback is run when the file descriptor is writable
+.It SUDO_PLUGIN_EV_PERSIST
+event is persistent and remains enabled until explicitly deleted
+.It SUDO_PLUGIN_EV_SIGNAL
+callback is run when the specified signal is received
+.El
+.Pp
+The
+.Ev SUDO_PLUGIN_EV_PERSIST
+flag may be ORed with any of the event types.
+It is also possible to OR
+.Ev SUDO_PLUGIN_EV_READ
+and
+.Ev SUDO_PLUGIN_EV_WRITE
+together to run the callback when a descriptor is ready to be
+either read from or written to.
+All other event values are mutually exclusive.
+.It sudo_plugin_ev_callback_t Fa callback
+.Bd -literal -compact
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what,
+ void *closure);
+.Ed
+.Pp
+The function to call when an event is triggered.
+The
+.Fn callback
+function is run with the following arguments:
+.Bl -tag -width 4n
+.It Fa fd
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+.It Fa what
+The event type that triggered that callback.
+For events that have multiple event types (for example
+.Ev SUDO_PLUGIN_EV_READ
+and
+.Ev SUDO_PLUGIN_EV_WRITE )
+or have an associated timeout,
+.Fa what
+can be used to determine why the callback was run.
+.It Fa closure
+The generic pointer that was specified in the
+.Fn set
+function.
+.El
+.It closure
+A generic pointer that will be passed to the callback function.
+.El
+.Pp
+The
+.Fn set
+function returns 1 on success, and \-1 if a error occurred.
+.It Fn add
+.Bd -literal -compact
+int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+.Ed
+.Pp
+The
+.Fn add
+function adds the event
+.Fa pev
+to
+.Nm sudo Ns No 's
+event loop.
+The event must have previously been initialized via the
+.Fn set
+function.
+If the
+.Fa timeout
+argument is not NULL, it should specify a (relative) timeout after
+which the event will be triggered if the main event criteria has
+not been met.
+This is often used to implement an I/O timeout where the event
+will fire if a descriptor is not ready within a certain time
+period.
+If the event is already present in the event loop, its
+.Fa timeout
+will be adjusted to match the new value, if any.
+.Pp
+The
+.Fn add
+function returns 1 on success, and \-1 if a error occurred.
+.It Fn del
+.Bd -literal -compact
+int (*del)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn del
+function deletes the event
+.Fa pev
+from
+.Nm sudo Ns No 's
+event loop.
+Deleted events can be added back via the
+.Fn add
+function.
+.Pp
+The
+.Fn del
+function returns 1 on success, and \-1 if a error occurred.
+.It Fn pending
+.Bd -literal -compact
+int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+.Ed
+.Pp
+The
+.Fn pending
+function can be used to determine whether one or more events is pending.
+The
+.Fa events
+argument specifies which events to check for.
+See the
+.Fn set
+function for a list of valid event types.
+If
+.Dv SUDO_PLUGIN_EV_TIMEOUT
+is specified in
+.Dv events ,
+the event has an associated timeout and the
+.Fa ts
+pointer is non-NULL, it will be filled in with the remaining time.
+.It Fn fd
+.Bd -literal -compact
+int (*fd)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn fd
+function returns the descriptor or signal number associated with
+the event
+.Fa pev .
+.It Fn setbase
+.Bd -literal -compact
+void (*setbase)(struct sudo_plugin_event *pev, void *base);
+.Ed
+.Pp
+The
+.Fn setbase
+function sets the underlying event
+.Fa base
+for
+.Fa pev
+to the specified value.
+This can be used to move an event created via
+.Fn event_alloc
+to a new event loop allocated by sudo's event subsystem.
+If
+.Fa base
+is
+.Dv NULL ,
+.Fa pev Ns 's
+event base is reset to the default value, which corresponds to
+.Nm sudo Ns 's
+main event loop.
+Using this function requires linking the plugin with the sudo_util
+library.
+It is unlikely to be used outside of the
+.Nm sudoers
+plugin.
+.It Fn loopbreak
+.Bd -literal -compact
+void (*loopbreak)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn loopbreak
+function causes
+.Nm sudo Ns No 's
+event loop to exit immediately and the running command to be terminated.
+.It Fn free
+.Bd -literal -compact
+void (*free)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn free
+function deletes the event
+.Fa pev
+from the event loop and frees the memory associated with it.
+.El
+.Ss Remote command execution
+The
+.Nm sudo
+front end does not support running remote commands.
+However, starting with
+.Nm sudo
+1.8.8, the
+.Fl h
+option may be used to specify a remote host that is passed
+to the policy plugin.
+A plugin may also accept a
+.Em runas_user
+in the form of
+.Dq user@hostname
+which will work with older versions of
+.Nm sudo .
+It is anticipated that remote commands will be supported by executing a
+.Dq helper
+program.
+The policy plugin should setup the execution environment such that the
+.Nm sudo
+front end will run the helper which, in turn, will connect to the
+remote host and run the command.
+.Pp
+For example, the policy plugin could utilize
+.Nm ssh
+to perform remote command execution.
+The helper program would be responsible for running
+.Nm ssh
+with the proper options to use a private key or certificate
+that the remote host will accept and run a program
+on the remote host that would setup the execution environment
+accordingly.
+.Pp
+Note that remote
+.Nm sudoedit
+functionality must be handled by the policy plugin, not
+.Nm sudo
+itself as the front end has no knowledge that a remote command is
+being executed.
+This may be addressed in a future revision of the plugin API.
+.Ss Conversation API
+If the plugin needs to interact with the user, it may do so via the
+.Fn conversation
+function.
+A plugin should not attempt to read directly from the standard input
+or the user's tty (neither of which are guaranteed to exist).
+The caller must include a trailing newline in
+.Li msg
+if one is to be printed.
+.Pp
+A
+.Fn printf Ns -style
+function is also available that can be used to display informational
+or error messages to the user, which is usually more convenient for
+simple messages where no use input is required.
+.Pp
+.Em Conversation function structures
+.Pp
+The conversation function takes as arguments pointers to the following
+structures:
+.Bd -literal
+struct sudo_conv_message {
+#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
+#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
+#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
+#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
+#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
+#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
+#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */
+ int msg_type;
+ int timeout;
+ const char *msg;
+};
+
+#define SUDO_CONV_REPL_MAX 1023
+
+struct sudo_conv_reply {
+ char *reply;
+};
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+ unsigned int version;
+ void *closure;
+ sudo_conv_callback_fn_t on_suspend;
+ sudo_conv_callback_fn_t on_resume;
+};
+.Ed
+.Pp
+Pointers to the
+.Fn conversation
+and
+.Fn printf Ns -style
+functions are passed
+in to the plugin's
+.Fn open
+function when the plugin is initialized.
+The following type definitions can be used in the declaration of the
+.Fn open
+function:
+.Bd -literal
+typedef int (*sudo_conv_t)(int num_msgs,
+ const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
+.Ed
+.Pp
+To use the
+.Fn conversation
+function, the plugin must pass an array of
+.Li sudo_conv_message
+and
+.Li sudo_conv_reply
+structures.
+There must be a
+.Li struct sudo_conv_message
+and
+.Li struct sudo_conv_reply
+for
+each message in the conversation, that is, both arrays must have the same
+number of elements.
+Each
+.Li struct sudo_conv_reply
+must have its
+.Em reply
+member initialized to
+.Dv NULL .
+The
+.Li struct sudo_conv_callback
+pointer, if not
+.Dv NULL ,
+should contain function pointers to be called when the
+.Nm sudo
+process is suspended and/or resumed during conversation input.
+The
+.Fa on_suspend
+and
+.Fa on_resume
+functions are called with the signal that caused
+.Nm sudo
+to be suspended and the
+.Fa closure
+pointer from the
+.Li struct sudo_conv_callback .
+These functions should return 0 on success and \-1 on error.
+On error, the conversation will end and the conversation function
+will return a value of \-1.
+The intended use is to allow the plugin to release resources, such as locks,
+that should not be held indefinitely while suspended and then reacquire them
+when the process is resumed.
+Note that the functions are not actually invoked from within a signal handler.
+.Pp
+The
+.Em msg_type
+must be set to one of the following values:
+.Bl -tag -width 4n
+.It SUDO_CONV_PROMPT_ECHO_OFF
+Prompt the user for input with echo disabled;
+this is generally used for passwords.
+The reply will be stored in the
+.Em replies
+array, and it will never be
+.Dv NULL .
+.It SUDO_CONV_PROMPT_ECHO_ON
+Prompt the user for input with echo enabled.
+The reply will be stored in the
+.Em replies
+array, and it will never be
+.Dv NULL .
+.It SUDO_CONV_ERROR_MSG
+Display an error message.
+The message is written to the standard error unless the
+.Dv SUDO_CONV_PREFER_TTY
+flag is set, in which case it is written to the user's terminal if possible.
+.It SUDO_CONV_INFO_MSG
+Display a message.
+The message is written to the standard output unless the
+.Dv SUDO_CONV_PREFER_TTY
+flag is set, in which case it is written to the user's terminal if possible.
+.It SUDO_CONV_PROMPT_MASK
+Prompt the user for input but echo an asterisk character for each
+character read.
+The reply will be stored in the
+.Em replies
+array, and it will never be
+.Dv NULL .
+This can be used to provide visual feedback to the user while reading
+sensitive information that should not be displayed.
+.El
+.Pp
+In addition to the above values, the following flag bits may also be set:
+.Bl -tag -width 4n
+.It SUDO_CONV_PROMPT_ECHO_OK
+Allow input to be read when echo cannot be disabled
+when the message type is
+.Dv SUDO_CONV_PROMPT_ECHO_OFF
+or
+.Dv SUDO_CONV_PROMPT_MASK .
+By default,
+.Nm sudo
+will refuse to read input if the echo cannot be disabled for those
+message types.
+.It SUDO_CONV_PREFER_TTY
+When displaying a message via
+.Dv SUDO_CONV_ERROR_MSG
+or
+.Dv SUDO_CONV_INFO_MSG ,
+try to write the message to the user's terminal.
+If the terminal is unavailable, the standard error or standard output
+will be used, depending upon whether
+The user's terminal is always used when possible for input,
+this flag is only used for output.
+.Dv SUDO_CONV_ERROR_MSG
+or
+.Dv SUDO_CONV_INFO_MSG
+was used.
+.El
+.Pp
+The
+.Em timeout
+in seconds until the prompt will wait for no more input.
+A zero value implies an infinite timeout.
+.Pp
+The plugin is responsible for freeing the reply buffer located in each
+.Li struct sudo_conv_reply ,
+if it is not
+.Dv NULL .
+.Dv SUDO_CONV_REPL_MAX
+represents the maximum length of the reply buffer (not including
+the trailing NUL character).
+In practical terms, this is the longest password
+.Nm sudo
+will support.
+.Pp
+The
+.Fn printf Ns -style
+function uses the same underlying mechanism as the
+.Fn conversation
+function but only supports
+.Dv SUDO_CONV_INFO_MSG
+and
+.Dv SUDO_CONV_ERROR_MSG
+for the
+.Em msg_type
+parameter.
+It can be more convenient than using the
+.Fn conversation
+function if no user reply is needed and supports standard
+.Fn printf
+escape sequences.
+.Pp
+See the sample plugin for an example of the
+.Fn conversation
+function usage.
+.Ss Plugin invocation order
+As of
+.Nm sudo
+1.9.0, the plugin
+.Fn open
+and
+.Fn close
+functions are called in the
+following order:
+.Bl -enum
+.It
+audit open
+.It
+policy open
+.It
+approval open
+.It
+approval close
+.It
+I/O log open
+.It
+command runs
+.It
+command exits
+.It
+I/O log close
+.It
+policy close
+.It
+audit close
+.It
+sudo exits
+.El
+.Pp
+Prior to
+.Nm sudo
+1.9.0, the I/O log
+.Fn close
+function was called
+.Em after
+the policy
+.Fn close
+function.
+.Ss Sudoers group plugin API
+The
+.Nm sudoers
+plugin supports its own plugin interface to allow non-Unix
+group lookups.
+This can be used to query a group source other than the standard Unix
+group database.
+Two sample group plugins are bundled with
+.Nm sudo ,
+.Em group_file
+and
+.Em system_group ,
+are detailed in
+.Xr sudoers @mansectform@ .
+Third party group plugins include a QAS AD plugin available from Quest Software.
+.Pp
+A group plugin must declare and populate a
+.Li sudoers_group_plugin
+struct in the global scope.
+This structure contains pointers to the functions that implement plugin
+initialization, cleanup and group lookup.
+.Bd -literal
+struct sudoers_group_plugin {
+ unsigned int version;
+ int (*init)(int version, sudo_printf_t sudo_printf,
+ char *const argv[]);
+ void (*cleanup)(void);
+ int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+};
+.Ed
+.Pp
+The
+.Li sudoers_group_plugin
+struct has the following fields:
+.Bl -tag -width 4n
+.It version
+The
+.Li version
+field should be set to GROUP_API_VERSION.
+.Pp
+This allows
+.Nm sudoers
+to determine the API version the group plugin
+was built against.
+.It init
+.Bd -literal -compact
+int (*init)(int version, sudo_printf_t plugin_printf,
+ char *const argv[]);
+.Ed
+.Pp
+The
+.Fn init
+function is called after
+.Em sudoers
+has been parsed but
+before any policy checks.
+It returns 1 on success, 0 on failure (or if the plugin is not configured),
+and \-1 if a error occurred.
+If an error occurs, the plugin may call the
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It version
+The version passed in by
+.Nm sudoers
+allows the plugin to determine the
+major and minor version number of the group plugin API supported by
+.Nm sudoers .
+.It plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error message to the user.
+Returns the number of characters printed on success and \-1 on failure.
+.It argv
+A
+.Dv NULL Ns -terminated
+array of arguments generated from the
+.Em group_plugin
+option in
+.Em sudoers .
+If no arguments were given,
+.Em argv
+will be
+.Dv NULL .
+.El
+.It cleanup
+.Bd -literal -compact
+void (*cleanup)();
+.Ed
+.Pp
+The
+.Fn cleanup
+function is called when
+.Nm sudoers
+has finished its
+group checks.
+The plugin should free any memory it has allocated and close open file handles.
+.It query
+.Bd -literal -compact
+int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+.Ed
+.Pp
+The
+.Fn query
+function is used to ask the group plugin whether
+.Em user
+is a member of
+.Em group .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It user
+The name of the user being looked up in the external group database.
+.It group
+The name of the group being queried.
+.It pwd
+The password database entry for
+.Em user ,
+if any.
+If
+.Em user
+is not
+present in the password database,
+.Em pwd
+will be
+.Dv NULL .
+.El
+.El
+.Pp
+.Em Group API Version Macros
+.Bd -literal
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
+ GROUP_API_VERSION_MINOR)
+.Ed
+For getters and setters see the
+.Sx Policy plugin API .
+.Sh PLUGIN API CHANGELOG
+The following revisions have been made to the Sudo Plugin API.
+.Bl -tag -width 4n
+.It Version 1.0
+Initial API version.
+.It Version 1.1 (sudo 1.8.0)
+The I/O logging plugin's
+.Fn open
+function was modified to take the
+.Li command_info
+list as an argument.
+.It Version 1.2 (sudo 1.8.5)
+The Policy and I/O logging plugins'
+.Fn open
+functions are now passed
+a list of plugin parameters if any are specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A simple hooks API has been introduced to allow plugins to hook in to the
+system's environment handling functions.
+.Pp
+The
+.Li init_session
+Policy plugin function is now passed a pointer
+to the user environment which can be updated as needed.
+This can be used to merge in environment variables stored in the PAM
+handle before a command is run.
+.It Version 1.3 (sudo 1.8.7)
+Support for the
+.Em exec_background
+entry has been added to the
+.Li command_info
+list.
+.Pp
+The
+.Em max_groups
+and
+.Em plugin_dir
+entries were added to the
+.Li settings
+list.
+.Pp
+The
+.Fn version
+and
+.Fn close
+functions are now optional.
+Previously, a missing
+.Fn version
+or
+.Fn close
+function would result in a crash.
+If no policy plugin
+.Fn close
+function is defined, a default
+.Fn close
+function will be provided by the
+.Nm sudo
+front end that displays a warning if the command could not be
+executed.
+.Pp
+The
+.Nm sudo
+front end now installs default signal handlers to trap common signals
+while the plugin functions are run.
+.It Version 1.4 (sudo 1.8.8)
+The
+.Em remote_host
+entry was added to the
+.Li settings
+list.
+.It Version 1.5 (sudo 1.8.9)
+The
+.Em preserve_fds
+entry was added to the
+.Li command_info
+list.
+.It Version 1.6 (sudo 1.8.11)
+The behavior when an I/O logging plugin returns an error
+.Pq \-1
+has changed.
+Previously, the
+.Nm sudo
+front end took no action when the
+.Fn log_ttyin ,
+.Fn log_ttyout ,
+.Fn log_stdin ,
+.Fn log_stdout ,
+or
+.Fn log_stderr
+function returned an error.
+.Pp
+The behavior when an I/O logging plugin returns 0 has changed.
+Previously, output from the command would be displayed to the
+terminal even if an output logging function returned 0.
+.It Version 1.7 (sudo 1.8.12)
+The
+.Em plugin_path
+entry was added to the
+.Li settings
+list.
+.Pp
+The
+.Em debug_flags
+entry now starts with a debug file path name and may occur multiple
+times if there are multiple plugin-specific Debug lines in the
+.Xr sudo.conf @mansectform@ file.
+.It Version 1.8 (sudo 1.8.15)
+The
+.Em sudoedit_checkdir
+and
+.Em sudoedit_follow
+entries were added to the
+.Li command_info
+list.
+The default value of
+.Em sudoedit_checkdir
+was changed to true in sudo 1.8.16.
+.Pp
+The sudo
+.Em conversation
+function now takes a pointer to a
+.Li struct sudo_conv_callback
+as its fourth argument.
+The
+.Li sudo_conv_t
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
+.It Version 1.9 (sudo 1.8.16)
+The
+.Em execfd
+entry was added to the
+.Li command_info
+list.
+.It Version 1.10 (sudo 1.8.19)
+The
+.Em umask
+entry was added to the
+.Li user_info
+list.
+The
+.Em iolog_group ,
+.Em iolog_mode ,
+and
+.Em iolog_user
+entries were added to the
+.Li command_info
+list.
+.It Version 1.11 (sudo 1.8.20)
+The
+.Em timeout
+entry was added to the
+.Li settings
+list.
+.It Version 1.12 (sudo 1.8.21)
+The
+.Li change_winsize
+field was added to the io_plugin struct.
+.It Version 1.13 (sudo 1.8.26)
+The
+.Li log_suspend
+field was added to the io_plugin struct.
+.It Version 1.14 (sudo 1.8.29)
+The
+.Em umask_override
+entry was added to the
+.Li command_info
+list.
+.It Version 1.15 (sudo 1.9.0)
+The
+.Em cwd_optional
+entry was added to the
+.Li command_info
+list.
+.Pp
+The
+.Em event_alloc
+field was added to the policy_plugin and io_plugin structs.
+.Pp
+The
+.Fa errstr
+argument was added to the policy and I/O plugin functions
+which the plugin function can use to return an error string.
+This string may be used by the audit plugin to report failure or
+error conditions set by the other plugins.
+.Pp
+The
+.Fn close
+function is now is called regardless of whether or not a command
+was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+.Pp
+.Dv SUDO_CONV_REPL_MAX
+has increased from 255 to 1023 bytes.
+.Pp
+Support for audit and approval plugins was added.
+.It Version 1.16 (sudo 1.9.3)
+Initial resource limit values were added to the
+.Li user_info
+list.
+.Pp
+The
+.Em cmnd_chroot
+and
+.Em cmnd_cwd
+enties were added to the
+.Li settings
+list.
+.It Version 1.17 (sudo 1.9.4)
+The
+.Em event_alloc
+field was added to the audit_plugin and approval_plugin structs.
+.El
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_plugin_python.man.in b/doc/sudo_plugin_python.man.in
new file mode 100644
index 0000000..919ecd9
--- /dev/null
+++ b/doc/sudo_plugin_python.man.in
@@ -0,0 +1,1890 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+.\"
+.\" 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.
+.\"
+.TH "SUDO_PLUGIN_PYTHON" "5" "February 19, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_plugin_python\fR
+\- Sudo Plugin API (Python)
+.SH "DESCRIPTION"
+Starting with version 1.9,
+\fBsudo\fR
+plugins can be written in python.
+The API closely follows the C
+\fBsudo\fR
+plugin API described by
+sudo_plugin(@mansectform@).
+.PP
+The supported plugins types are:
+.PP
+.RS 4n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+Policy plugin
+.TP 3n
+\fB\(bu\fR
+I/O plugin
+.TP 3n
+\fB\(bu\fR
+Audit plugin
+.TP 3n
+\fB\(bu\fR
+Approval plugin
+.TP 3n
+\fB\(bu\fR
+Group provider plugin
+.RE
+.PD
+.PP
+Python plugin support needs to be explicitly enabled at build time
+with the configure option
+\(lq--enable-python\(rq.
+Python version 3.0 or higher is required.
+.SS "Sudo Python Plugin Base"
+A plugin written in Python should be a class in a python file that
+inherits from
+\fIsudo.Plugin\fR.
+The
+\fIsudo.Plugin\fR
+base class has no real purpose other than to identify this class as a plugin.
+.PP
+The only implemented method is a constructor, which stores the
+keyword arguments it receives as fields (member variables) in the object.
+This is intended as a convenience to allow you to avoid writing the
+constructor yourself.
+.PP
+For example:
+.nf
+.sp
+.RS 6n
+import sudo
+
+class MySudoPlugin(sudo.Plugin):
+ # example constructor (optional)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # example destructor (optional)
+ def __del__(self):
+ pass
+.RE
+.fi
+.PP
+Both the constructor and destructor are optional and can be omitted.
+.PP
+The customized Plugin class should define a few plugin-specific methods.
+When the plugin loads,
+\fBsudo\fR
+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
+result code, as documented in
+sudo_plugin(@mansctsu@),
+that indicates whether or not the method was successful.
+The Python sudo module defines the following constants to improve readability:
+.RS 4n
+.TS
+l l.
+.PP
+\fBDefine\fR \fBValue\fR
+.PP
+\fRsudo.RC.OK\fR 1
+.PP
+\fRsudo.RC.ACCEPT\fR 1
+.PP
+\fRsudo.RC.REJECT\fR 0
+.PP
+\fRsudo.RC.ERROR\fR -1
+.PP
+\fRsudo.RC.USAGE_ERROR\fR -2
+.TE
+.RE
+.PP
+If a function returns
+\fINone\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
+\fRsudo.RC.ERROR\fR.
+If that is not acceptable, you must catch the exception and handle it yourself.
+.PP
+Instead of just returning
+\fRsudo.RC.ERROR\fR
+or
+\fRsudo.RC.REJECT\fR
+result code the plugin can also provide a message describing the problem.
+This can be done by raising one of the special exceptions:
+.nf
+.sp
+.RS 6n
+raise sudo.PluginError("Message")
+raise sudo.PluginReject("Message")
+.RE
+.fi
+.PP
+This added message will be used by the audit plugins.
+Both exceptions inherit from
+\fRsudo.PluginException\fR
+.SS "Python Plugin Loader"
+Running the Python interpreter and bridging between C and Python is
+handled by the
+\fBsudo\fR
+plugin
+\fRpython_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
+plugin it is loading as arguments.
+.PP
+Example usage in
+sudo.conf(@mansectform@):
+.nf
+.sp
+.RS 6n
+Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Example group provider plugin usage in the
+\fIsudoers\fR
+file:
+.nf
+.sp
+.RS 6n
+Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
+.RE
+.fi
+.PP
+The plugin arguments are as follows:
+.TP 6n
+ModulePath
+The path of a python file which contains the class of the sudo Python plugin.
+It must be either an absolute path or a path relative to the sudo Python plugin
+directory: "@plugindir@/python".
+.TP 6n
+ClassName
+(Optional.) The name of the class implementing the sudo Python plugin.
+If not supplied, the one and only sudo.Plugin that is present in the module
+will be used.
+If there are multiple such plugins in the module (or none), it
+will result in an error.
+.SS "Policy plugin API"
+Policy plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 6n
+Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Currently, only a single policy plugin may be specified in
+sudo.conf(@mansectform@).
+.PP
+A policy plugin may have the following member functions:
+.TP 6n
+\fBconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C sudo plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Policy Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the policy plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.RE
+.TP 6n
+\fBcheck_policy\fR
+.nf
+.RS 6n
+check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcheck_policy\fR()
+function is called by
+\fBsudo\fR
+to determine whether the user is allowed to run the specified command.
+Implementing this function is mandatory for a policy plugin.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargv\fR
+A tuple describing the command the user wishes to run.
+.TP 6n
+\fIenv_add\fR
+Additional environment variables specified by the user on the command line in
+the form of a tuple of
+\(lqkey=value\(rq
+pairs.
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert them to a dictionary.
+.PP
+This function should return a result code or a tuple in the following format:
+.nf
+.sp
+.RS 12n
+return (rc, command_info_out, argv_out, user_env_out)
+.RE
+.fi
+.sp
+The tuple values are as follows:
+.TP 6n
+\fIrc\fR
+The result of the policy check, one of the
+\fRsudo.RC.*\fR
+constants.
+\fRsudo.RC.ACCEPT\fR
+if the command is allowed,
+\fRsudo.RC.REJECT\fR
+if not allowed,
+\fRsudo.RC.ERROR\fR
+for a general error, or
+\fRsudo.RC.USAGE_ERROR\fR
+for a usage error.
+.TP 6n
+\fIcommand_info_out\fR
+Optional (only required when the command is accepted).
+Information about the command being run in the form of
+\(lqkey=value\(rq
+strings.
+.sp
+To accept a command, at the very minimum the plugin must set in the
+\fIcommand\fR,
+\fIrunas_uid\fR
+and
+\fIrunas_gid\fR
+keys.
+.sp
+For a list of recognized keys and supported values,
+see the
+\fBcheck_policy\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.TP 6n
+\fIargv_out\fR
+Optional (only required when the command is accepted).
+The arguments to pass to the
+execve(2)
+system call when executing the command.
+.TP 6n
+\fIuser_env_out\fR
+Optional (only required when the command is accepted).
+The environment to use when executing the command in the form of a
+tuple of strings in
+\(lqkey=value\(rq
+format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBinit_session\fR
+.nf
+.RS 6n
+init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Perform session setup (optional).
+The
+\fBinit_session\fR()
+function is called before
+\fBsudo\fR
+sets up the
+execution environment for the command before any uid or gid changes.
+.sp
+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
+if the user is not present in the password database.
+.sp
+Example conversion:
+.nf
+.RS 12n
+user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
+.RE
+.fi
+.TP 6n
+\fIuser_env\fR
+The environment the command will run in.
+This is a tuple of strings in
+\(lqkey=value\(rq
+format.
+.PP
+This function should return a result code or a tuple in the following format:
+.nf
+.sp
+.RS 10n
+return (rc, user_env_out)
+.RE
+.fi
+.sp
+The tuple values are as follows:
+.TP 6n
+\fIrc\fR
+The result of the session init, one of the
+\fRsudo.RC.*\fR
+constants.
+\fRsudo.RC.OK\fR
+on success, 0 on failure, or
+\fRsudo.RC.ERROR\fR
+if an error occurred.
+.TP 6n
+\fIuser_env_out\fR
+Optional.
+If the
+\fBinit_session\fR()
+function needs to modify the user environment, it can return the new
+environment in
+\fIuser_env_out\fR.
+If this is omitted, no changes will be made to
+\fIuser_env\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBlist\fR
+.nf
+.RS 6n
+list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
+.RE
+.fi
+.RS 6n
+.sp
+List available privileges for the invoking user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargv\fR
+If not set to
+\fINone\fR,
+an argument vector describing a command the user wishes to check
+against the policy.
+.TP 6n
+\fIis_verbose\fR
+Flag indicating whether to list in verbose mode or not.
+.TP 6n
+\fIuser\fR
+The name of a different user to list privileges for if the policy allows it.
+If
+\fINone\fR,
+the plugin should list the privileges of the invoking user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBvalidate\fR
+.nf
+.RS 6n
+validate(self)
+.RE
+.fi
+.RS 6n
+.sp
+For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
+.RE
+.TP 6n
+\fBinvalidate\fR
+.nf
+.RS 6n
+invalidate(self, remove: int)
+.RE
+.fi
+.RS 6n
+.sp
+For policy plugins that cache authentication credentials, this function is used to invalidate the credentials (optional).
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIremove\fR
+If this flag is set, the plugin may remove the credentials instead of simply
+invalidating them.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int)
+.RE
+.fi
+.RS 6n
+.sp
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBclose\fR
+.br
+.nf
+.RS 6n
+close(self, exit_status: int, error: int)
+.RE
+.fi
+.RS 6n
+.sp
+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
+\fBsudo\fR
+attempts to execute the command.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The exit status of the command if was executed, otherwise -1.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+errno set by the
+execve(2)
+system call, otherwise 0.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Policy plugin example"
+Sudo ships with an example Python policy plugin.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 0n
+Plugin python_policy python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_policy_plugin.py \e
+ ClassName=SudoPolicyPlugin
+.RE
+.fi
+.PP
+Be aware, however, that you cannot enable the Python policy plugin
+in addition to another policy plugin, such as
+sudoers(@mansectform@).
+.SS "I/O plugin API"
+I/O plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 6n
+Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Sudo supports loading multiple I/O plugins.
+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
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C sudo plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python I/O Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.RE
+.TP 6n
+\fBopen\fR
+.nf
+.RS 6n
+open(self, argv: Tuple[str, ...],
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+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:
+.sp
+.RS 10n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+It only gets called before the user would execute some command
+(and not for a version query for example).
+.TP 3n
+\fB\(bu\fR
+Other arguments of the C API
+\fBopen\fR()
+function are received through the constructor.
+.RE
+.sp
+The function arguments are as follows:
+.PD
+.TP 6n
+\fIargv\fR
+A tuple of the arguments describing the command the user wishes to run.
+.TP 6n
+\fIcommand_info\fR
+Information about the command being run in the form of
+\(lqkey=value\(rq
+strings.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.sp
+The
+\fBopen\fR()
+function should return a result code, one of the
+\fRsudo.RC.*\fR
+constants.
+If the function returns
+\fRsudo.RC.REJECT\fR,
+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
+.nf
+.RS 6n
+log_ttyin(self, buf: str) -> int
+log_ttyout(self, buf: str) -> int
+log_stdin(self, buf: str) -> int
+log_stdout(self, buf: str) -> int
+log_stderr(self, buf: str) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Receive the user input or output of the terminal device and
+application standard input / output / error.
+See the matching calls in
+sudo_plugin(@mansectform@).
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The input (or output) buffer in the form of a string.
+.PP
+The function should return a result code, one of the
+\fRsudo.RC.*\fR
+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.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.sp
+If an input logging function rejects the data by returning
+\fRsudo.RC.REJECT\fR,
+the command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning
+\fRsudo.RC.REJECT\fR,
+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
+.nf
+.RS 6n
+change_winsize(self, line: int, cols: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Called whenever the window size of the terminal changes.
+The function arguments are as follows:
+.TP 6n
+\fIline\fR
+The number of lines of the terminal.
+.TP 6n
+\fIcols\fR
+The number of columns of the terminal.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBlog_suspend\fR
+.nf
+.RS 6n
+log_suspend(self, signo: int) -> int
+.RE
+.fi
+.RS 6n
+Called whenever a command is suspended or resumed.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIsigno\fR
+.br
+The number of the signal that caused the command to be suspended or
+\fRSIGCONT\fR
+if the command was resumed.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int)
+.RE
+.fi
+.RS 6n
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBclose\fR
+.br
+.nf
+.RS 6n
+close(self, exit_status: int, error: int) -> None
+.RE
+.fi
+.RS 6n
+Called when a command execution finished.
+.sp
+Works the same as the
+\fBclose\fR()
+function in the C sudo plugin API, except that it only gets called if
+\fBsudo\fR
+attempts to execute the command.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The exit status of the command if was executed, otherwise -1.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+errno set by the
+execve(2)
+system call, otherwise 0.
+.PD 0
+.PP
+.RE
+.PD
+.SS "I/O plugin example"
+Sudo ships a Python I/O plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 6n
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_io_plugin.py \e
+ ClassName=SudoIOPlugin
+.RE
+.fi
+.SS "Audit plugin API"
+Audit plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 6n
+Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+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):
+.TP 6n
+\fBconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C sudo plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Audit Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBopen\fR
+.nf
+.RS 6n
+open(self, submit_optind: int,
+ submit_argv: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector sudo was invoked with, including all command line options.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBclose\fR
+.br
+.nf
+.RS 6n
+close(self, status_type: int, status: int) -> None
+.RE
+.fi
+.RS 6n
+.sp
+Called when sudo is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIstatus_type\fR
+The type of status being passed.
+One of the sudo.EXIT_REASON.* constants.
+.TP 6n
+\fIstatus\fR
+Depending on the value of
+\fIstatus_type\fR,
+this value is either
+ignored, the command's exit status as returned by the
+wait(2)
+system call, the value of
+\fRerrno\fR
+set by the
+execve(2)
+system call, or the value of
+\fRerrno\fR
+resulting from an error in the
+\fBsudo\fR
+front end.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBaccept\fR
+.nf
+.RS 6n
+accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
+ run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that accepted the command or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that accepted the command, currently either
+\fRsudo.PLUGIN_TYPE.POLICY\fR,
+\fRsudo.PLUGIN_TYPE.APPROVAL\fR
+or
+\fRsudo.PLUGIN_TYPE.SUDO\fR.
+The
+\fBaccept\fR()
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+\fIcommand_info\fR
+may include information from an I/O logging plugin as well.
+.sp
+Typically, an audit plugin is interested in either the accept status from
+the
+\fBsudo\fR
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+\fBaccept\fR()
+and
+\fBreject\fR()
+functions will
+\fIboth\fR
+be called.
+.TP 6n
+command_info
+A vector of information describing the command being run.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.TP 6n
+run_argv
+Argument vector describing a command that will be run.
+.TP 6n
+run_envp
+The environment the command will be run with.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBreject\fR
+.nf
+.RS 6n
+reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a command or action is rejected by the policy
+plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that rejected the command.
+.TP 6n
+plugin_type
+The type of plugin that rejected the command, currently either
+\fRsudo.PLUGIN_TYPE.POLICY\fR,
+\fRsudo.PLUGIN_TYPE.APPROVAL\fR
+or
+\fRsudo.PLUGIN_TYPE.IO\fR.
+.sp
+Unlike the
+\fBaccept\fR()
+function, the
+\fBreject\fR()
+function is not called on behalf of the
+\fBsudo\fR
+front-end.
+.TP 6n
+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
+.TP 6n
+command_info
+A vector of information describing the rejected command.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBerror\fR
+.br
+.nf
+.RS 6n
+error(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a plugin or the
+\fBsudo\fR
+front-end returns an error.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that generated the error or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that generated the error, or
+\fRSUDO_FRONT_END\fR
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description, it will be
+\fINone\fR
+.TP 6n
+command_info
+A vector of information describing the command.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Audit plugin example"
+Sudo ships a Python Audit plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 6n
+Plugin python_audit python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_audit_plugin.py \e
+ ClassName=SudoAuditPlugin
+.RE
+.fi
+.PP
+It will log the plugin accept / reject / error results to the output.
+.SS "Approval plugin API"
+Approval plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 6n
+Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Sudo supports loading multiple approval plugins.
+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
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
+ submit_optind: int, submit_argv: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C sudo plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Approval Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector sudo was invoked with, including all command line options.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Display the version. (Same as for all the other plugins.)
+.RE
+.TP 6n
+\fBcheck\fR
+.br
+.nf
+.RS 6n
+check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
+ run_env: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called after policy plugin's check_policy has succeeded.
+It can reject execution of the command by returning sudo.RC.REJECT or
+raising the special exception:
+.nf
+.sp
+.RS 12n
+raise sudo.PluginReject("some message")
+.RE
+.fi
+.sp
+with the message describing the problem.
+In the latter case, the audit plugins will get the description.
+.sp
+The function arguments are as follows:
+.TP 6n
+command_info
+A vector of information describing the command that will run.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.TP 6n
+run_argv
+Argument vector describing a command that will be run.
+.TP 6n
+run_env
+The environment the command will be run with.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Approval plugin example"
+Sudo ships a Python Approval plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 6n
+Plugin python_approval python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_approval_plugin.py \e
+ ClassName=BusinessHoursApprovalPlugin
+.RE
+.fi
+.PP
+It will only allow execution of commands in the "business hours" (from Monday
+to Friday between 8:00 and 17:59:59).
+.SS "Sudoers group provider plugin API"
+A group provider plugin is registered in the
+sudoers(@mansectform@)
+file.
+For example:
+.nf
+.sp
+.RS 6n
+Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
+.RE
+.fi
+.PP
+Currently, only a single group plugin can be registered in
+\fIsudoers\fR.
+.PP
+A group provider plugin may have the following member functions:
+.TP 6n
+\fBconstructor\fR
+.nf
+.RS 6n
+__init__(self, args: Tuple[str, ...], version: str)
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargs\fR
+The plugin options passed as arguments in the
+\fIsudoers\fR
+file plugin registration.
+All the arguments are free form strings (not necessarily in
+\(lqkey=value\(rq
+format).
+.TP 6n
+\fIversion\fR
+The version of the Python Group Plugin API.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fBquery\fR
+.br
+.nf
+.RS 6n
+query(self, user: str, group: str, user_pwd: Tuple)
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBquery\fR()
+function is used to ask the group plugin whether
+\fIuser\fR
+is a member of
+\fIgroup\fR.
+This method is required.
+.RE
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIuser\fR
+The name of the user being looked up in the external group database.
+.TP 6n
+\fIgroup\fR
+.br
+The name of the group being queried.
+.TP 6n
+\fIuser_pwd\fR
+The password database entry for the user, if any.
+If
+\fIuser\fR
+is not present in the password database,
+\fIuser_pwd\fR
+will be
+\fRNULL\fR.
+.SS "Group plugin example"
+Sudo ships a Python group plugin example.
+To try it, register it in the
+\fIsudoers\fR
+file by adding the following lines:
+.nf
+.sp
+.RS 6n
+Defaults group_plugin="python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_group_plugin.py \e
+ ClassName=SudoGroupPlugin"
+.RE
+.fi
+.PP
+The example plugin will tell
+\fBsudo\fR
+that the user
+\fItest\fR
+is part of the non-unix group
+\fImygroup\fR.
+If you add a rule that uses this group, it will affect the
+\fItest\fR
+user.
+For example:
+.nf
+.sp
+.RS 6n
+%:mygroup ALL=(ALL) NOPASSWD: ALL
+.RE
+.fi
+.PP
+Will allow user
+\fItest\fR
+to run
+\fBsudo\fR
+without a password.
+.SS "Hook function API"
+The hook function API is currently not supported for plugins
+written in Python.
+.SS "Conversation API"
+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
+class.
+This is the Python equivalent of the
+\fBconversation\fR()
+function in the C 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
+\fBsudo.ConvMessage\fR
+class specifies how the user interaction should occur:
+.nf
+.sp
+.RS 4n
+sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
+.RE
+.fi
+.PP
+\fBsudo.ConvMessage\fR
+member variables:
+.TP 6n
+\fImsg_type\fR
+Specifies the type of the conversation.
+See the
+\fRsudo.CONV.*\fR
+constants below.
+.TP 6n
+\fImsg\fR
+The message to display to the user.
+The caller must include a trailing newline in
+\fRmsg\fR
+if one is to be displayed.
+.TP 6n
+\fItimeout\fR
+Optional.
+The maximum amount of time for the conversation in seconds.
+If the timeout is exceeded, the
+\fBsudo.conv\fR()
+function will raise a
+\fRsudo.ConversationInterrupted\fR
+exception.
+The default is to wait forever (no timeout).
+.PP
+To specify the message type, the following constants are available:
+.PP
+.RS 4n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.PROMPT_ECHO_OFF
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.PROMPT_ECHO_ON
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.ERROR_MSG
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.INFO_MSG
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.PROMPT_MASK
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.PROMPT_ECHO_OK
+.TP 3n
+\fB\(bu\fR
+sudo.CONV.PREFER_TTY
+.RE
+.PD
+.PP
+See the
+sudo_plugin(@mansectform@)
+manual for a description of the message types.
+.PP
+The
+\fBsudo.conv\fR()
+function performs the actual user interaction:
+.nf
+.sp
+.RS 4n
+sudo.conv(message(s), on_suspend=suspend_function,
+ on_resume=resume_function)
+.RE
+.fi
+.PP
+The function arguments are as follows:
+.TP 6n
+\fImessage(s)\fR
+One of more messages (of type
+\fBsudo.ConvMessage\fR),
+each describing a conversation.
+At least one message is required.
+.TP 6n
+\fIon_suspend\fR
+An optional callback function which gets called if the conversation
+is suspended, for example by the user pressing control-Z.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.TP 6n
+\fIon_resume\fR
+An optional callback function which gets called when the previously
+suspended conversation is resumed.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.PP
+The
+\fBsudo.conv\fR()
+function can raise the following exceptions:
+.TP 6n
+\fBsudo.SudoException\fR
+If the conversation fails, for example when the conversation function is not
+available.
+.TP 6n
+\fBsudo.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"
+Sudo ships with an example plugin demonstrating the Python conversation API.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 6n
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_conversation.py \e
+ ClassName=ReasonLoggerIOPlugin
+.RE
+.fi
+.SS "Information / error display API"
+.nf
+.RS 0n
+sudo.log_info(string(s), sep=" ", end="\en")
+sudo.log_error(string(s), sep=" ", end="\en")
+.RE
+.fi
+.PP
+To display information to the user, the
+\fBsudo.log_info\fR()
+function can be used.
+To display error messages, use
+\fBsudo.log_error\fR().
+The syntax is similar to the Python
+\fBprint\fR()
+function.
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIstring(s)\fR
+One or more strings to display.
+.TP 6n
+\fIsep\fR
+An optional string which will be used as the separator between the
+specified strings.
+The default is a space character,
+(\(oq\ \(cq).
+.TP 6n
+\fIend\fR
+An optional string which will be displayed at the end of the message.
+The default is a new line character
+(\(oq\en\(cq).
+.SS "Debug API"
+Debug messages are not visible to the user and are only logged debugging
+is explicitly enabled in
+sudo.conf(@mansectform@).
+Python plugins can use the
+\fBsudo.debug\fR()
+function to make use of
+\fBsudo\fR's
+debug system.
+.PP
+\fIEnabling debugging in sudo.conf\fR
+.PP
+To enable debug messages, add a
+\fRDebug\fR
+line to
+sudo.conf(@mansectform@)
+with the program set to
+\fIpython_plugin.so\fR.
+For example, to store debug output in
+\fI/var/log/sudo_python_debug\fR,
+use a line like the following:
+.nf
+.sp
+.RS 6n
+Debug python_plugin.so /var/log/sudo_python_debug \e
+ plugin@trace,c_calls@trace
+.RE
+.fi
+.PP
+The debug options are in the form of multiple
+\(lqsubsystem@level\(rq
+strings, separated by commas
+(\(oq\&,\(cq).
+For example to just see the debug output of
+\fBsudo.debug\fR()
+calls, use:
+.nf
+.sp
+.RS 6n
+Debug python_plugin.so /var/log/sudo_python_debug plugin@trace
+.RE
+.fi
+.PP
+See
+sudo_conf(@mansectform@)
+for more details.
+.PP
+The most interesting subsystems for Python plugin development are:
+.TP 6n
+\fIplugin\fR
+Logs each
+\fBsudo.debug\fR()
+API call.
+.TP 6n
+\fIpy_calls\fR
+Logs whenever a C function calls into the python module.
+For example, calling the
+\fB__init__\fR()
+function.
+.TP 6n
+\fIc_calls\fR
+Logs whenever python calls into a C
+\fBsudo\fR
+API function.
+.TP 6n
+\fIinternal\fR
+Logs internal functions of the python language wrapper plugin.
+.TP 6n
+\fIsudo_cb\fR
+Logs when
+\fBsudo\fR
+calls into the python plugin API.
+.TP 6n
+\fIload\fR
+Logs python plugin loading / unloading events.
+.PP
+You can also specify
+\(lqall\(rq
+as the subsystem name to log debug messages for all subsystems.
+.PP
+The
+\fBsudo.debug\fR()
+function is defined as:
+.nf
+.sp
+.RS 4n
+sudo.debug(level, message(s))
+.RE
+.fi
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIlevel\fR
+.br
+an integer, use one of the log level constants below
+.TP 6n
+\fImessage(s)\fR
+one or more messages to log
+.PP
+\fIAvailable log levels:\fR
+.TS
+l l l.
+.PP
+\fBsudo.conf name\fR \fBPython constant\fR \fBdescription\fR
+.PP
+crit sudo.DEBUG.CRIT only critical messages
+.PP
+err sudo.DEBUG.ERROR
+.PP
+warn sudo.DEBUG.WARN
+.PP
+notice sudo.DEBUG.NOTICE
+.PP
+diag sudo.DEBUG.DIAG
+.PP
+info sudo.DEBUG.INFO
+.PP
+trace sudo.DEBUG.TRACE
+.PP
+debug sudo.DEBUG.DEBUG very extreme verbose debugging
+.TE
+.PP
+\fIUsing the logging module\fR
+.PP
+Alternatively, a plugin can use the built in logging module of Python as well.
+Sudo adds its log handler to the root logger, so by default all output of a
+logger will get forwarded to sudo log system, as it would call sudo.debug.
+.PP
+The log handler of sudo will map each Python log level of a message to
+the appropriate sudo debug level.
+Note however, that sudo debug system will only get the messages 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.
+.SS "Debug example"
+Sudo ships an example debug plugin by default.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 6n
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_debugging.py \e
+ ClassName=DebugDemoPlugin
+
+Debug python_plugin.so \e
+ /var/log/sudo_python_debug plugin@trace,c_calls@trace
+.RE
+.fi
+.SS "Option conversion API"
+The Python plugin API includes two convenience functions to
+convert options in
+\(lqkey=value\(rq
+format to a dictionary and vice versa.
+.TP 6n
+options_as_dict
+.nf
+.RS 6n
+options_as_dict(options)
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIoptions\fR
+An iterable (tuple, list, etc.) of strings, each in
+\(lqkey=value\(rq
+format.
+This is how the plugin API passes options and settings to a Python plugin.
+.PP
+The function returns the resulting dictionary.
+Each string of the passed in
+\fIoptions\fR
+will be split at the first equal sign
+(\(oq\&=\(cq)
+into a
+\fIkey\fR
+and
+\fIvalue\fR.
+Dictionary keys will never contain this symbol (but values may).
+.RE
+.TP 6n
+options_from_dict
+.nf
+.RS 6n
+options_from_dict(options_dict)
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIoptions_dict\fR
+A dictionary where both the key and the value are strings.
+Note that the key should not contain an equal sign
+(\(oq\&=\(cq),
+otherwise the resulting string will have a different meaning.
+However, this is not currently enforced.
+.PP
+The function returns a tuple containing the strings in
+\(lqkey=value\(rq
+form for each key and value in the
+\fIoptions_dict\fR
+dictionary passed in.
+This is how the plugin API accepts options and settings.
+.RE
+.SH "PLUGIN API CHANGELOG (Python)"
+None yet
+.SH "LIMITATIONS"
+Only a maximum number 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.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+Python plugin support is currently considered experimental.
+.PP
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SECURITY CONSIDERATIONS"
+All Python plugin handling is implemented inside the
+\fRpython_plugin.so\fR
+dynamic plugin.
+Therefore, if no Python plugin is registered in
+sudo.conf(@mansectform@)
+or the
+\fIsudoers\fR
+file,
+\fBsudo\fR
+will not load the Python interpreter or the Python libraries.
+.PP
+By default, a Python plugin can only import Python modules which are
+owned by
+\fIroot\fR
+and are only writable by the owner.
+The reason for this is to prevent a file getting imported accidentally
+which is modifiable by a non-root user.
+As
+\fBsudo\fR
+plugins run as
+\fIroot\fR,
+accidentally importing such file would make it possible for any user
+(having write access) to execute any code with administrative rights.
+.PP
+However, during development of a plugin this might not be very convenient.
+The
+sudo.conf(@mansectform@)
+\fRdeveloper_mode\fR
+option can be used to disable it.
+For example:
+.RS 6n
+Set developer_mode true
+.RE
+.PP
+Please note that this creates a security risk, so it is not recommended
+on critical systems such as a desktop machine for daily use, but is intended
+to be used in development environments (VM, container, etc).
+Before enabling developer mode, ensure you understand the implications.
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_plugin_python.mdoc.in b/doc/sudo_plugin_python.mdoc.in
new file mode 100644
index 0000000..ba87971
--- /dev/null
+++ b/doc/sudo_plugin_python.mdoc.in
@@ -0,0 +1,1541 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+.\"
+.\" 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.
+.\"
+.Dd February 19, 2020
+.Dt SUDO_PLUGIN_PYTHON @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_plugin_python
+.Nd Sudo Plugin API (Python)
+.Sh DESCRIPTION
+Starting with version 1.9,
+.Nm sudo
+plugins can be written in python.
+The API closely follows the C
+.Nm sudo
+plugin API described by
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The supported plugins types are:
+.Pp
+.Bl -bullet -compact -offset 4n -width 1n
+.It
+Policy plugin
+.It
+I/O plugin
+.It
+Audit plugin
+.It
+Approval plugin
+.It
+Group provider plugin
+.El
+.Pp
+Python plugin support needs to be explicitly enabled at build time
+with the configure option
+.Dq --enable-python .
+Python version 3.0 or higher is required.
+.Ss Sudo Python Plugin Base
+A plugin written in Python should be a class in a python file that
+inherits from
+.Em sudo.Plugin .
+The
+.Em sudo.Plugin
+base class has no real purpose other than to identify this class as a plugin.
+.Pp
+The only implemented method is a constructor, which stores the
+keyword arguments it receives as fields (member variables) in the object.
+This is intended as a convenience to allow you to avoid writing the
+constructor yourself.
+.Pp
+For example:
+.Bd -literal -offset indent
+import sudo
+
+class MySudoPlugin(sudo.Plugin):
+ # example constructor (optional)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # example destructor (optional)
+ def __del__(self):
+ pass
+.Ed
+.Pp
+Both the constructor and destructor are optional and can be omitted.
+.Pp
+The customized Plugin class should define a few plugin-specific methods.
+When the plugin loads,
+.Nm sudo
+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
+result code, as documented in
+.Xr sudo_plugin @mansctsu@ ,
+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
+.It Sy Define Ta Sy Value
+.It Dv sudo.RC.OK Ta 1
+.It Dv sudo.RC.ACCEPT Ta 1
+.It Dv sudo.RC.REJECT Ta 0
+.It Dv sudo.RC.ERROR Ta -1
+.It Dv sudo.RC.USAGE_ERROR Ta -2
+.El
+.Pp
+If a function returns
+.Em 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
+.Dv sudo.RC.ERROR .
+If that is not acceptable, you must catch the exception and handle it yourself.
+.Pp
+Instead of just returning
+.Dv sudo.RC.ERROR
+or
+.Dv sudo.RC.REJECT
+result code the plugin can also provide a message describing the problem.
+This can be done by raising one of the special exceptions:
+.Bd -literal -offset indent
+raise sudo.PluginError("Message")
+raise sudo.PluginReject("Message")
+.Ed
+.Pp
+This added message will be used by the audit plugins.
+Both exceptions inherit from
+.Dv sudo.PluginException
+.Ss Python Plugin Loader
+Running the Python interpreter and bridging between C and Python is
+handled by the
+.Nm sudo
+plugin
+.Li 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
+plugin it is loading as arguments.
+.Pp
+Example usage in
+.Xr sudo.conf @mansectform@ :
+.Bd -literal -offset indent
+Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
+Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Example group provider plugin usage in the
+.Em sudoers
+file:
+.Bd -literal -offset indent
+Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
+.Ed
+.Pp
+The plugin arguments are as follows:
+.Bl -tag -width 4n
+.It ModulePath
+The path of a python file which contains the class of the sudo Python plugin.
+It must be either an absolute path or a path relative to the sudo Python plugin
+directory: "@plugindir@/python".
+.It ClassName
+(Optional.) The name of the class implementing the sudo Python plugin.
+If not supplied, the one and only sudo.Plugin that is present in the module
+will be used.
+If there are multiple such plugins in the module (or none), it
+will result in an error.
+.El
+.Ss Policy plugin API
+Policy plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset indent
+Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Currently, only a single policy plugin may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A policy plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Sy constructor
+.Bd -literal
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C sudo plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Policy Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the policy plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Sy check_policy
+.Bd -literal -compact
+check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
+.Ed
+.Pp
+The
+.Fn check_policy
+function is called by
+.Nm sudo
+to determine whether the user is allowed to run the specified command.
+Implementing this function is mandatory for a policy plugin.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+A tuple describing the command the user wishes to run.
+.It Fa env_add
+Additional environment variables specified by the user on the command line in
+the form of a tuple of
+.Dq key=value
+pairs.
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert them to a dictionary.
+.El
+.Pp
+This function should return a result code or a tuple in the following format:
+.Bd -literal -offset indent
+return (rc, command_info_out, argv_out, user_env_out)
+.Ed
+.Pp
+The tuple values are as follows:
+.Bl -tag -width 4n
+.It Fa rc
+The result of the policy check, one of the
+.Dv sudo.RC.*
+constants.
+.Dv sudo.RC.ACCEPT
+if the command is allowed,
+.Dv sudo.RC.REJECT
+if not allowed,
+.Dv sudo.RC.ERROR
+for a general error, or
+.Dv sudo.RC.USAGE_ERROR
+for a usage error.
+.It Fa command_info_out
+Optional (only required when the command is accepted).
+Information about the command being run in the form of
+.Dq key=value
+strings.
+.Pp
+To accept a command, at the very minimum the plugin must set in the
+.Em command ,
+.Em runas_uid
+and
+.Em runas_gid
+keys.
+.Pp
+For a list of recognized keys and supported values,
+see the
+.Fn check_policy
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Fa argv_out
+Optional (only required when the command is accepted).
+The arguments to pass to the
+.Xr execve 2
+system call when executing the command.
+.It Fa user_env_out
+Optional (only required when the command is accepted).
+The environment to use when executing the command in the form of a
+tuple of strings in
+.Dq key=value
+format.
+.El
+.It Sy init_session
+.Bd -literal -compact
+init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
+.Ed
+.Pp
+Perform session setup (optional).
+The
+.Fn init_session
+function is called before
+.Nm sudo
+sets up the
+execution environment for the command before any uid or gid changes.
+.Pp
+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
+if the user is not present in the password database.
+.Pp
+Example conversion:
+.Bd -literal -compact -offset indent
+user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
+.Ed
+.It Fa user_env
+The environment the command will run in.
+This is a tuple of strings in
+.Dq key=value
+format.
+.El
+.Pp
+This function should return a result code or a tuple in the following format:
+.Bd -literal -offset 4n
+return (rc, user_env_out)
+.Ed
+.Pp
+The tuple values are as follows:
+.Bl -tag -width 4n
+.It Fa rc
+The result of the session init, one of the
+.Dv sudo.RC.*
+constants.
+.Dv sudo.RC.OK
+on success, 0 on failure, or
+.Dv sudo.RC.ERROR
+if an error occurred.
+.It Fa user_env_out
+Optional.
+If the
+.Fn init_session
+function needs to modify the user environment, it can return the new
+environment in
+.Fa user_env_out .
+If this is omitted, no changes will be made to
+.Fa user_env .
+.El
+.It Sy list
+.Bd -literal -compact
+list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
+.Ed
+.Pp
+List available privileges for the invoking user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+If not set to
+.Em None ,
+an argument vector describing a command the user wishes to check
+against the policy.
+.It Fa is_verbose
+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 ,
+the plugin should list the privileges of the invoking user.
+.El
+.It Sy 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
+.Bd -literal -compact
+invalidate(self, remove: int)
+.Ed
+.Pp
+For policy plugins that cache authentication credentials, this function is used to invalidate the credentials (optional).
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa remove
+If this flag is set, the plugin may remove the credentials instead of simply
+invalidating them.
+.El
+.It Sy show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int)
+.Ed
+.Pp
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Sy close
+.Bd -literal -compact
+close(self, exit_status: int, error: int)
+.Ed
+.Pp
+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
+.Nm sudo
+attempts to execute the command.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The exit status of the command if was executed, otherwise -1.
+.It Fa error
+If the command could not be executed, this is set to the value of
+errno set by the
+.Xr execve 2
+system call, otherwise 0.
+.El
+.El
+.Ss Policy plugin example
+Sudo ships with an example Python policy plugin.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal
+Plugin python_policy python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_policy_plugin.py \e
+ ClassName=SudoPolicyPlugin
+.Ed
+.Pp
+Be aware, however, that you cannot enable the Python policy plugin
+in addition to another policy plugin, such as
+.Xr sudoers @mansectform@ .
+.Ss I/O plugin API
+I/O plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset indent
+Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Sudo supports loading multiple I/O plugins.
+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
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C sudo plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python I/O Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Sy open
+.Bd -literal -compact
+open(self, argv: Tuple[str, ...],
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+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:
+.Pp
+.Bl -bullet -compact -offset 4n -width 1n
+.It
+It only gets called before the user would execute some command
+(and not for a version query for example).
+.It
+Other arguments of the C API
+.Fn open
+function are received through the constructor.
+.El
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+A tuple of the arguments describing the command the user wishes to run.
+.It Fa command_info
+Information about the command being run in the form of
+.Dq key=value
+strings.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The
+.Fn open
+function should return a result code, one of the
+.Dv sudo.RC.*
+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
+.Bd -literal -compact
+log_ttyin(self, buf: str) -> int
+log_ttyout(self, buf: str) -> int
+log_stdin(self, buf: str) -> int
+log_stdout(self, buf: str) -> int
+log_stderr(self, buf: str) -> int
+.Ed
+.Pp
+Receive the user input or output of the terminal device and
+application standard input / output / error.
+See the matching calls in
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The input (or output) buffer in the form of a string.
+.El
+.Pp
+The function should return a result code, one of the
+.Dv sudo.RC.*
+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.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.Pp
+If an input logging function rejects the data by returning
+.Dv sudo.RC.REJECT ,
+the command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+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
+.Bd -literal -compact
+change_winsize(self, line: int, cols: int) -> int
+.Ed
+.Pp
+Called whenever the window size of the terminal changes.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa line
+The number of lines of the terminal.
+.It Fa cols
+The number of columns of the terminal.
+.El
+.It Sy log_suspend
+.Bd -literal -compact
+log_suspend(self, signo: int) -> int
+.Ed
+Called whenever a command is suspended or resumed.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa signo
+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
+.Bd -literal -compact
+show_version(self, is_verbose: int)
+.Ed
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Sy close
+.Bd -literal -compact
+close(self, exit_status: int, error: int) -> None
+.Ed
+Called when a command execution finished.
+.Pp
+Works the same as the
+.Fn close
+function in the C sudo plugin API, except that it only gets called if
+.Nm sudo
+attempts to execute the command.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The exit status of the command if was executed, otherwise -1.
+.It Fa error
+If the command could not be executed, this is set to the value of
+errno set by the
+.Xr execve 2
+system call, otherwise 0.
+.El
+.El
+.Ss I/O plugin example
+Sudo ships a Python I/O plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset indent
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_io_plugin.py \e
+ ClassName=SudoIOPlugin
+.Ed
+.Ss Audit plugin API
+Audit plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset indent
+Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+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):
+.Bl -tag -width 4n
+.It Sy constructor
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C sudo plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Audit Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.It Sy open
+.Bd -literal -compact
+open(self, submit_optind: int,
+ submit_argv: Tuple[str, ...]) -> int
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+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
+.Bd -literal -compact
+close(self, status_type: int, status: int) -> None
+.Ed
+.Pp
+Called when sudo is finished, shortly before it exits.
+.Pp
+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.
+.It Fa status
+Depending on the value of
+.Fa status_type ,
+this value is either
+ignored, the command's exit status as returned by the
+.Xr wait 2
+system call, the value of
+.Li errno
+set by the
+.Xr execve 2
+system call, or the value of
+.Li errno
+resulting from an error in the
+.Nm sudo
+front end.
+.El
+.It Sy show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int) -> int
+.Ed
+.Pp
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Sy 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
+.Ed
+.Pp
+This function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that accepted the command or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that accepted the command, currently either
+.Dv sudo.PLUGIN_TYPE.POLICY ,
+.Dv sudo.PLUGIN_TYPE.APPROVAL
+or
+.Dv sudo.PLUGIN_TYPE.SUDO .
+The
+.Fn accept
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+.Fa command_info
+may include information from an I/O logging plugin as well.
+.Pp
+Typically, an audit plugin is interested in either the accept status from
+the
+.Nm sudo
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+.Fn accept
+and
+.Fn reject
+functions will
+.Em both
+be called.
+.It command_info
+A vector of information describing the command being run.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.It run_argv
+Argument vector describing a command that will be run.
+.It run_envp
+The environment the command will be run with.
+.El
+.It Sy reject
+.Bd -literal -compact
+reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called when a command or action is rejected by the policy
+plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that rejected the command.
+.It plugin_type
+The type of plugin that rejected the command, currently either
+.Dv sudo.PLUGIN_TYPE.POLICY ,
+.Dv sudo.PLUGIN_TYPE.APPROVAL
+or
+.Dv sudo.PLUGIN_TYPE.IO .
+.Pp
+Unlike the
+.Fn accept
+function, the
+.Fn reject
+function is not called on behalf of the
+.Nm sudo
+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
+.
+.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
+.Bd -literal -compact
+error(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called when a plugin or the
+.Nm sudo
+front-end returns an error.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that generated the error or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that generated the error, or
+.Dv SUDO_FRONT_END
+for the
+.Nm sudo
+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
+.
+.It command_info
+A vector of information describing the command.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.El
+.El
+.Ss Audit plugin example
+Sudo ships a Python Audit plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset indent
+Plugin python_audit python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_audit_plugin.py \e
+ ClassName=SudoAuditPlugin
+.Ed
+.Pp
+It will log the plugin accept / reject / error results to the output.
+.Ss Approval plugin API
+Approval plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset indent
+Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Sudo supports loading multiple approval plugins.
+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
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
+ submit_optind: int, submit_argv: Tuple[str, ...])
+.Ed
+.Pp
+Optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C sudo plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Approval Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+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
+.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
+.Bd -literal -compact
+check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
+ run_env: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called after policy plugin's check_policy has succeeded.
+It can reject execution of the command by returning sudo.RC.REJECT or
+raising the special exception:
+.Bd -literal -offset indent
+raise sudo.PluginReject("some message")
+.Ed
+.Pp
+with the message describing the problem.
+In the latter case, the audit plugins will get the description.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It command_info
+A vector of information describing the command that will run.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.It run_argv
+Argument vector describing a command that will be run.
+.It run_env
+The environment the command will be run with.
+.El
+.El
+.Ss Approval plugin example
+Sudo ships a Python Approval plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset indent
+Plugin python_approval python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_approval_plugin.py \e
+ ClassName=BusinessHoursApprovalPlugin
+.Ed
+.Pp
+It will only allow execution of commands in the "business hours" (from Monday
+to Friday between 8:00 and 17:59:59).
+.Ss Sudoers group provider plugin API
+A group provider plugin is registered in the
+.Xr sudoers @mansectform@
+file.
+For example:
+.Bd -literal -offset indent
+Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
+.Ed
+.Pp
+Currently, only a single group plugin can be registered in
+.Em sudoers .
+.Pp
+A group provider plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Sy constructor
+.Bd -literal -compact
+__init__(self, args: Tuple[str, ...], version: str)
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa args
+The plugin options passed as arguments in the
+.Em sudoers
+file plugin registration.
+All the arguments are free form strings (not necessarily in
+.Dq key=value
+format).
+.It Fa version
+The version of the Python Group Plugin API.
+.El
+.It Sy query
+.Bd -literal -compact
+query(self, user: str, group: str, user_pwd: Tuple)
+.Ed
+.Pp
+The
+.Fn query
+function is used to ask the group plugin whether
+.Fa user
+is a member of
+.Fa group .
+This method is required.
+.El
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user
+The name of the user being looked up in the external group database.
+.It Fa group
+The name of the group being queried.
+.It Fa user_pwd
+The password database entry for the user, if any.
+If
+.Fa user
+is not present in the password database,
+.Fa user_pwd
+will be
+.Dv NULL .
+.El
+.Ss Group plugin example
+Sudo ships a Python group plugin example.
+To try it, register it in the
+.Em sudoers
+file by adding the following lines:
+.Bd -literal -offset indent
+Defaults group_plugin="python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_group_plugin.py \e
+ ClassName=SudoGroupPlugin"
+.Ed
+.Pp
+The example plugin will tell
+.Nm sudo
+that the user
+.Em test
+is part of the non-unix group
+.Em mygroup .
+If you add a rule that uses this group, it will affect the
+.Em test
+user.
+For example:
+.Bd -literal -offset indent
+%:mygroup ALL=(ALL) NOPASSWD: ALL
+.Ed
+.Pp
+Will allow user
+.Em test
+to run
+.Nm sudo
+without a password.
+.Ss Hook function API
+The hook function API is currently not supported for plugins
+written in Python.
+.Ss Conversation API
+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
+class.
+This is the Python equivalent of the
+.Fn conversation
+function in the C 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
+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
+member variables:
+.Bl -tag -width 4n
+.It Fa msg_type
+Specifies the type of the conversation.
+See the
+.Dv sudo.CONV.*
+constants below.
+.It Fa msg
+The message to display to the user.
+The caller must include a trailing newline in
+.Li msg
+if one is to be displayed.
+.It Fa timeout
+Optional.
+The maximum amount of time for the conversation in seconds.
+If the timeout is exceeded, the
+.Fn sudo.conv
+function will raise a
+.Dv sudo.ConversationInterrupted
+exception.
+The default is to wait forever (no timeout).
+.El
+.Pp
+To specify the message type, the following constants are available:
+.Pp
+.Bl -bullet -compact -offset 4n -width 1n
+.It
+sudo.CONV.PROMPT_ECHO_OFF
+.It
+sudo.CONV.PROMPT_ECHO_ON
+.It
+sudo.CONV.ERROR_MSG
+.It
+sudo.CONV.INFO_MSG
+.It
+sudo.CONV.PROMPT_MASK
+.It
+sudo.CONV.PROMPT_ECHO_OK
+.It
+sudo.CONV.PREFER_TTY
+.El
+.Pp
+See the
+.Xr sudo_plugin @mansectform@
+manual for a description of the message types.
+.Pp
+The
+.Fn sudo.conv
+function performs the actual user interaction:
+.Bd -literal -offset 4n
+sudo.conv(message(s), on_suspend=suspend_function,
+ on_resume=resume_function)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa message(s)
+One of more messages (of type
+.Sy sudo.ConvMessage ) ,
+each describing a conversation.
+At least one message is required.
+.It Fa on_suspend
+An optional callback function which gets called if the conversation
+is suspended, for example by the user pressing control-Z.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.It Fa on_resume
+An optional callback function which gets called when the previously
+suspended conversation is resumed.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.El
+.Pp
+The
+.Fn sudo.conv
+function can raise the following exceptions:
+.Bl -tag -width 4n
+.It Sy sudo.SudoException
+If the conversation fails, for example when the conversation function is not
+available.
+.It Sy 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
+.Ss Conversation example
+Sudo ships with an example plugin demonstrating the Python conversation API.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset indent
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_conversation.py \e
+ ClassName=ReasonLoggerIOPlugin
+.Ed
+.Ss Information / error display API
+.Bd -literal
+sudo.log_info(string(s), sep=" ", end="\en")
+sudo.log_error(string(s), sep=" ", end="\en")
+.Ed
+.Pp
+To display information to the user, the
+.Fn sudo.log_info
+function can be used.
+To display error messages, use
+.Fn sudo.log_error .
+The syntax is similar to the Python
+.Fn print
+function.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa string(s)
+One or more strings to display.
+.It Fa sep
+An optional string which will be used as the separator between the
+specified strings.
+The default is a space character,
+.Pq Sq \ .
+.It Fa end
+An optional string which will be displayed at the end of the message.
+The default is a new line character
+.Pq Sq \en .
+.El
+.Ss Debug API
+Debug messages are not visible to the user and are only logged debugging
+is explicitly enabled in
+.Xr sudo.conf @mansectform@ .
+Python plugins can use the
+.Fn sudo.debug
+function to make use of
+.Nm sudo Ns No 's
+debug system.
+.Pp
+.Em Enabling debugging in sudo.conf
+.Pp
+To enable debug messages, add a
+.Li Debug
+line to
+.Xr sudo.conf @mansectform@
+with the program set to
+.Pa python_plugin.so .
+For example, to store debug output in
+.Pa /var/log/sudo_python_debug ,
+use a line like the following:
+.Bd -literal -offset indent
+Debug python_plugin.so /var/log/sudo_python_debug \e
+ plugin@trace,c_calls@trace
+.Ed
+.Pp
+The debug options are in the form of multiple
+.Dq subsystem@level
+strings, separated by commas
+.Pq Sq \&, .
+For example to just see the debug output of
+.Fn sudo.debug
+calls, use:
+.Bd -literal -offset indent
+Debug python_plugin.so /var/log/sudo_python_debug plugin@trace
+.Ed
+.Pp
+See
+.Xr sudo_conf @mansectform@
+for more details.
+.Pp
+The most interesting subsystems for Python plugin development are:
+.Bl -tag -width 4n
+.It Em plugin
+Logs each
+.Fn sudo.debug
+API call.
+.It Em py_calls
+Logs whenever a C function calls into the python module.
+For example, calling the
+.Fn __init__
+function.
+.It Em c_calls
+Logs whenever python calls into a C
+.Nm sudo
+API function.
+.It Em internal
+Logs internal functions of the python language wrapper plugin.
+.It Em sudo_cb
+Logs when
+.Nm sudo
+calls into the python plugin API.
+.It Em load
+Logs python plugin loading / unloading events.
+.El
+.Pp
+You can also specify
+.Dq all
+as the subsystem name to log debug messages for all subsystems.
+.Pp
+The
+.Fn sudo.debug
+function is defined as:
+.Bd -literal -offset 4n
+sudo.debug(level, message(s))
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa level
+an integer, use one of the log level constants below
+.It Fa message(s)
+one or more messages to log
+.El
+.Pp
+.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
+.El
+.Pp
+.Em Using the logging module
+.Pp
+Alternatively, a plugin can use the built in logging module of Python as well.
+Sudo adds its log handler to the root logger, so by default all output of a
+logger will get forwarded to sudo log system, as it would call sudo.debug.
+.Pp
+The log handler of sudo will map each Python log level of a message to
+the appropriate sudo debug level.
+Note however, that sudo debug system will only get the messages 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.
+.Ss Debug example
+Sudo ships an example debug plugin by default.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset indent
+Plugin python_io python_plugin.so \e
+ ModulePath=@prefix@/share/doc/sudo/examples/example_debugging.py \e
+ ClassName=DebugDemoPlugin
+
+Debug python_plugin.so \e
+ /var/log/sudo_python_debug plugin@trace,c_calls@trace
+.Ed
+.Ss Option conversion API
+The Python plugin API includes two convenience functions to
+convert options in
+.Dq key=value
+format to a dictionary and vice versa.
+.Bl -tag -width 4n
+.It options_as_dict
+.Bd -literal -compact
+options_as_dict(options)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa options
+An iterable (tuple, list, etc.) of strings, each in
+.Dq key=value
+format.
+This is how the plugin API passes options and settings to a Python plugin.
+.El
+.Pp
+The function returns the resulting dictionary.
+Each string of the passed in
+.Fa options
+will be split at the first equal sign
+.Pq Sq \&=
+into a
+.Em key
+and
+.Em value .
+Dictionary keys will never contain this symbol (but values may).
+.It options_from_dict
+.Bd -literal -compact
+options_from_dict(options_dict)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa options_dict
+A dictionary where both the key and the value are strings.
+Note that the key should not contain an equal sign
+.Pq Sq \&= ,
+otherwise the resulting string will have a different meaning.
+However, this is not currently enforced.
+.El
+.Pp
+The function returns a tuple containing the strings in
+.Dq key=value
+form for each key and value in the
+.Fa options_dict
+dictionary passed in.
+This is how the plugin API accepts options and settings.
+.El
+.Sh PLUGIN API CHANGELOG (Python)
+None yet
+.Sh LIMITATIONS
+Only a maximum number 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.
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+Python plugin support is currently considered experimental.
+.Pp
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SECURITY CONSIDERATIONS
+All Python plugin handling is implemented inside the
+.Li python_plugin.so
+dynamic plugin.
+Therefore, if no Python plugin is registered in
+.Xr sudo.conf @mansectform@
+or the
+.Em sudoers
+file,
+.Nm sudo
+will not load the Python interpreter or the Python libraries.
+.Pp
+By default, a Python plugin can only import Python modules which are
+owned by
+.Em root
+and are only writable by the owner.
+The reason for this is to prevent a file getting imported accidentally
+which is modifiable by a non-root user.
+As
+.Nm sudo
+plugins run as
+.Em root ,
+accidentally importing such file would make it possible for any user
+(having write access) to execute any code with administrative rights.
+.Pp
+However, during development of a plugin this might not be very convenient.
+The
+.Xr sudo.conf @mansectform@
+.Li developer_mode
+option can be used to disable it.
+For example:
+.Dl Set developer_mode true
+.Pp
+Please note that this creates a security risk, so it is not recommended
+on critical systems such as a desktop machine for daily use, but is intended
+to be used in development environments (VM, container, etc).
+Before enabling developer mode, ensure you understand the implications.
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_sendlog.man.in b/doc/sudo_sendlog.man.in
new file mode 100644
index 0000000..4d72d75
--- /dev/null
+++ b/doc/sudo_sendlog.man.in
@@ -0,0 +1,190 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.TH "SUDO_SENDLOG" "@mansectsu@" "May 12, 2020" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_sendlog\fR
+\- send sudo I/O log to log server
+.SH "SYNOPSIS"
+.HP 13n
+\fBsudo_sendlog\fR
+[\fB\-AnV\fR]
+[\fB\-b\fR\ \fIca_bundle\fR]
+[\fB\-c\fR\ \fIcert_file\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-i\fR\ \fIiolog-id\fR]
+[\fB\-k\fR\ \fIkey_file\fR]
+[\fB\-p\fR\ \fIport\fR]
+[\fB\-r\fR\ \fIrestart-point\fR]
+[\fB\-R\fR\ \fIreject-reason\fR]
+[\fB\-t\fR\ \fInumber\fR]
+\fIpath\fR
+.SH "DESCRIPTION"
+\fBsudo_sendlog\fR
+can be used to send the existing
+\fBsudoers\fR
+I/O log
+\fIpath\fR
+to a remote log server such as
+sudo_logsrvd(@mansectsu@)
+for central storage.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-A\fR, \fB\--accept-only\fR
+Only send the accept event, not the I/O associated with the log.
+This can be used to test the logging of accept events without
+any associated I/O.
+.TP 12n
+\fB\-b\fR, \fB\--ca-bundle\fR
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+.TP 12n
+\fB\-c\fR, \fB\--cert\fR
+The path to the client's certificate file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.TP 12n
+\fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-h\fR, \fB\--host\fR
+Connect to the specified
+\fIhost\fR
+instead of localhost.
+.TP 12n
+\fB\-i\fR, \fB\--iolog-id\fR
+Use the specified
+\fIiolog-id\fR
+when restarting a log transfer.
+The
+\fIiolog-id\fR
+is reported by the server when it creates the remote I/O log.
+This option may only be used in conjunction with the
+\fB\-r\fR
+option.
+.TP 12n
+\fB\-k\fR, \fB\--key\fR
+.br
+The path to the client's private key file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.TP 12n
+\fB\-n\fR, \fB\--no-verify\fR
+If specified, the server's certificate will not be verified during
+the TLS handshake.
+By default,
+\fBsudo_sendlog\fR
+verifies that the server's certificate is valid and that it contains either
+the server's host name or its IP address.
+This setting is only supported when the connection to the remote log server
+is secured with TLS.
+.TP 12n
+\fB\-p\fR, \fB\--port\fR
+Use the specified network
+\fIport\fR
+when connecting to the log server instead of the
+default, port 30344.
+.TP 12n
+\fB\-r\fR, \fB\--restart\fR
+Restart an interrupted connection to the log server.
+The specified
+\fIrestart-point\fR
+is used to tell the server the point in time at which to continue the log.
+The
+\fIrestart-point\fR
+is specified in the form
+\(lqseconds,nanoseconds\(rq
+and is usually the last commit point received from the server.
+The
+\fB\-i\fR
+option must also be specified when restarting a transfer.
+.TP 12n
+\fB\-R\fR, \fB\--reject\fR
+Send a reject event for the command using the specified
+\fIreject-reason\fR,
+even though it was actually accepted locally.
+This can be used to test the logging of reject events; no I/O
+will be sent.
+.TP 12n
+\fB\-t\fR, \fB\--test\fR
+Open
+\fInumber\fR
+simultaneous connections to the log server and send the specified
+I/O log file on each one.
+This option is useful for performance testing.
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo_sendlog\fR
+version and exit.
+.SS "Debugging sendlog"
+\fBsudo_sendlog\fR
+supports a flexible debugging framework that is configured via
+\fRDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+please refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front end configuration
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo(@mansectsu@),
+sudo_logsrvd(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo_sendlog\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo_sendlog\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudo_sendlog.mdoc.in b/doc/sudo_sendlog.mdoc.in
new file mode 100644
index 0000000..8ec887d
--- /dev/null
+++ b/doc/sudo_sendlog.mdoc.in
@@ -0,0 +1,176 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2020 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.
+.\"
+.Dd May 12, 2020
+.Dt SUDO_SENDLOG @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_sendlog
+.Nd send sudo I/O log to log server
+.Sh SYNOPSIS
+.Nm sudo_sendlog
+.Op Fl AnV
+.Op Fl b Ar ca_bundle
+.Op Fl c Ar cert_file
+.Op Fl h Ar host
+.Op Fl i Ar iolog-id
+.Op Fl k Ar key_file
+.Op Fl p Ar port
+.Op Fl r Ar restart-point
+.Op Fl R Ar reject-reason
+.Op Fl t Ar number
+.Ar path
+.Sh DESCRIPTION
+.Nm
+can be used to send the existing
+.Nm sudoers
+I/O log
+.Ar path
+to a remote log server such as
+.Xr sudo_logsrvd @mansectsu@
+for central storage.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl A , -accept-only
+Only send the accept event, not the I/O associated with the log.
+This can be used to test the logging of accept events without
+any associated I/O.
+.It Fl b , -ca-bundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+.It Fl c , -cert
+The path to the client's certificate file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.It Fl -help
+Display a short help message to the standard output and exit.
+.It Fl h , -host
+Connect to the specified
+.Ar host
+instead of localhost.
+.It Fl i , -iolog-id
+Use the specified
+.Ar iolog-id
+when restarting a log transfer.
+The
+.Ar iolog-id
+is reported by the server when it creates the remote I/O log.
+This option may only be used in conjunction with the
+.Fl r
+option.
+.It Fl k , -key
+The path to the client's private key file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.It Fl n , -no-verify
+If specified, the server's certificate will not be verified during
+the TLS handshake.
+By default,
+.Nm
+verifies that the server's certificate is valid and that it contains either
+the server's host name or its IP address.
+This setting is only supported when the connection to the remote log server
+is secured with TLS.
+.It Fl p , -port
+Use the specified network
+.Ar port
+when connecting to the log server instead of the
+default, port 30344.
+.It Fl r , -restart
+Restart an interrupted connection to the log server.
+The specified
+.Ar restart-point
+is used to tell the server the point in time at which to continue the log.
+The
+.Ar restart-point
+is specified in the form
+.Dq seconds,nanoseconds
+and is usually the last commit point received from the server.
+The
+.Fl i
+option must also be specified when restarting a transfer.
+.It Fl R , -reject
+Send a reject event for the command using the specified
+.Ar reject-reason ,
+even though it was actually accepted locally.
+This can be used to test the logging of reject events; no I/O
+will be sent.
+.It Fl t , -test
+Open
+.Ar number
+simultaneous connections to the log server and send the specified
+I/O log file on each one.
+This option is useful for performance testing.
+.It Fl V , -version
+Print the
+.Nm
+version and exit.
+.El
+.Ss Debugging sendlog
+.Nm
+supports a flexible debugging framework that is configured via
+.Li Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+please refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front end configuration
+.El
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers.ldap.man.in b/doc/sudoers.ldap.man.in
new file mode 100644
index 0000000..dc81ddb
--- /dev/null
+++ b/doc/sudoers.ldap.man.in
@@ -0,0 +1,1727 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2003-2020 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.
+.\"
+.TH "SUDOERS.LDAP" "@mansectform@" "October 29, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers.ldap\fR
+\- sudo LDAP configuration
+.SH "DESCRIPTION"
+In addition to the standard
+\fIsudoers\fR
+file,
+\fBsudo\fR
+may be configured
+via LDAP.
+This can be especially useful for synchronizing
+\fIsudoers\fR
+in a large, distributed environment.
+.PP
+Using LDAP for
+\fIsudoers\fR
+has several benefits:
+.TP 3n
+\fB\(bu\fR
+\fBsudo\fR
+no longer needs to read
+\fIsudoers\fR
+in its entirety.
+When LDAP is used, there are only two or three LDAP queries per invocation.
+This makes it especially fast and particularly usable in LDAP environments.
+.TP 3n
+\fB\(bu\fR
+\fBsudo\fR
+no longer exits if there is a typo in
+\fIsudoers\fR.
+It is not possible to load LDAP data into the server that does
+not conform to the sudoers schema, so proper syntax is guaranteed.
+It is still possible to have typos in a user or host name, but
+this will not prevent
+\fBsudo\fR
+from running.
+.TP 3n
+\fB\(bu\fR
+It is possible to specify per-entry options that override the global
+default options.
+\fI@sysconfdir@/sudoers\fR
+only supports default options and limited options associated with
+user/host/commands/aliases.
+The syntax is complicated and can be difficult for users to understand.
+Placing the options directly in the entry is more natural.
+.TP 3n
+\fB\(bu\fR
+The
+\fBvisudo\fR
+program is no longer needed.
+\fBvisudo\fR
+provides locking and syntax checking of the
+\fI@sysconfdir@/sudoers\fR
+file.
+Since LDAP updates are atomic, locking is no longer necessary.
+Because syntax is checked when the data is inserted into LDAP, there
+is no need for a specialized tool to check syntax.
+.SS "SUDOers LDAP container"
+The
+\fIsudoers\fR
+configuration is contained in the
+\fRou=SUDOers\fR
+LDAP container.
+.PP
+Sudo first looks for the
+\fRcn=defaults\fR
+entry in the SUDOers container.
+If found, the multi-valued
+\fRsudoOption\fR
+attribute is parsed in the same manner as a global
+\fRDefaults\fR
+line in
+\fI@sysconfdir@/sudoers\fR.
+In the following example, the
+\fRSSH_AUTH_SOCK\fR
+variable will be preserved in the environment for all users.
+.nf
+.sp
+.RS 4n
+dn: cn=defaults,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: env_keep+=SSH_AUTH_SOCK
+.RE
+.fi
+.PP
+The equivalent of a sudoer in LDAP is a
+\fRsudoRole\fR.
+It consists of the following attributes:
+.TP 6n
+\fBsudoUser\fR
+A user name, user-ID (prefixed with
+\(oq#\(cq),
+Unix group name or ID (prefixed with
+\(oq%\(cq
+or
+\(oq%#\(cq
+respectively), user netgroup (prefixed with
+\(oq+\(cq),
+or non-Unix group name or ID (prefixed with
+\(oq%:\(cq
+or
+\(oq%:#\(cq
+respectively).
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+Non-Unix group support is only available when an appropriate
+\fIgroup_plugin\fR
+is defined in the global
+\fIdefaults\fR
+\fRsudoRole\fR
+object.
+.TP 6n
+\fBsudoHost\fR
+A host name, IP address, IP network, or host netgroup (prefixed with a
+\(oq+\(cq).
+The special value
+\fRALL\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
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fRsudoRole\fR
+in which it resides will be ignored.
+Negated
+\fRsudoHost\fR
+entries are only supported by version 1.8.18 or higher.
+.TP 6n
+\fBsudoCommand\fR
+A fully-qualified Unix command name with optional command line arguments,
+potentially including globbing characters (aka wild cards).
+If a command name is preceded by an exclamation point,
+\(oq\&!\(cq,
+the user will be prohibited from running that command.
+.sp
+The built-in command
+\(lq\fRsudoedit\fR\(rq
+is used to permit a user to run
+\fBsudo\fR
+with the
+\fB\-e\fR
+option (or as
+\fBsudoedit\fR).
+It may take command line arguments just as a normal command does.
+Note that
+\(lq\fRsudoedit\fR\(rq
+is a command built into
+\fBsudo\fR
+itself and must be specified in without a leading path.
+.sp
+The special value
+\fRALL\fR
+will match any command.
+.sp
+If a command name is prefixed with a SHA-2 digest, it will
+only be allowed if the digest matches.
+This may be useful in situations where the user invoking
+\fBsudo\fR
+has write access to the command or its parent directory.
+The following digest formats are supported: sha224, sha256, sha384 and sha512.
+The digest name must be followed by a colon
+(\(oq:\&\(cq)
+and then the actual digest, in either hex or base64 format.
+For example, given the following value for sudoCommand:
+.nf
+.sp
+.RS 10n
+sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ /bin/ls
+.RE
+.fi
+.RS 6n
+.sp
+The user may only run
+\fI/bin/ls\fR
+if its sha224 digest matches the specified value.
+Command digests are only supported by version 1.8.7 or higher.
+.RE
+.TP 6n
+\fBsudoOption\fR
+Identical in function to the global options described above, but
+specific to the
+\fRsudoRole\fR
+in which it resides.
+.TP 6n
+\fBsudoRunAsUser\fR
+A user name or uid (prefixed with
+\(oq#\(cq)
+that commands may be run as or a Unix group (prefixed with a
+\(oq%\(cq)
+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
+will match any user.
+If a
+\fRsudoRunAsUser\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fRsudoRole\fR
+in which it resides will be ignored.
+If
+\fRsudoRunAsUser\fR
+is specified but empty, it will match the invoking user.
+If neither
+\fRsudoRunAsUser\fR
+nor
+\fRsudoRunAsGroup\fR
+are present, the value of the
+\fIrunas_default\fR
+\fRsudoOption\fR
+is used (defaults to
+\fR@runas_default@\fR).
+.sp
+The
+\fRsudoRunAsUser\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.0 and higher.
+Older versions of
+\fBsudo\fR
+use the
+\fRsudoRunAs\fR
+attribute instead.
+Negated
+\fRsudoRunAsUser\fR
+entries are only supported by version 1.8.26 or higher.
+.TP 6n
+\fBsudoRunAsGroup\fR
+A Unix group or gid (prefixed with
+\(oq#\(cq)
+that commands may be run as.
+The special value
+\fRALL\fR
+will match any group.
+If a
+\fRsudoRunAsGroup\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fRsudoRole\fR
+in which it resides will be ignored.
+.sp
+The
+\fRsudoRunAsGroup\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.0 and higher.
+Negated
+\fRsudoRunAsGroup\fR
+entries are only supported by version 1.8.26 or higher.
+.TP 6n
+\fBsudoNotBefore\fR
+A timestamp in the form
+\fRyyyymmddHHMMSSZ\fR
+that can be used to provide a start date/time for when the
+\fRsudoRole\fR
+will be valid.
+If multiple
+\fRsudoNotBefore\fR
+entries are present, the earliest is used.
+Note that timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.sp
+The
+\fRsudoNotBefore\fR
+attribute is only available in
+\fBsudo\fR
+versions 1.7.5 and higher and must be explicitly enabled via the
+\fBSUDOERS_TIMED\fR
+option in
+\fI@ldap_conf@\fR.
+.TP 6n
+\fBsudoNotAfter\fR
+A timestamp in the form
+\fRyyyymmddHHMMSSZ\fR
+that indicates an expiration date/time, after which the
+\fRsudoRole\fR
+will no longer be valid.
+If multiple
+\fRsudoNotAfter\fR
+entries are present, the last one is used.
+Note that timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.sp
+The
+\fRsudoNotAfter\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.5 and higher and must be explicitly enabled via the
+\fBSUDOERS_TIMED\fR
+option in
+\fI@ldap_conf@\fR.
+.TP 6n
+\fBsudoOrder\fR
+The
+\fRsudoRole\fR
+entries retrieved from the LDAP directory have no inherent order.
+The
+\fRsudoOrder\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
+attribute is chosen.
+This corresponds to the
+\(lqlast match\(rq
+behavior of the sudoers file.
+If the
+\fRsudoOrder\fR
+attribute is not present, a value of 0 is assumed.
+.sp
+The
+\fRsudoOrder\fR
+attribute is only available in
+\fBsudo\fR
+versions 1.7.5 and higher.
+.PP
+Each attribute listed above should contain a single value, but there
+may be multiple instances of each attribute type.
+A
+\fRsudoRole\fR
+must contain at least one
+\fRsudoUser\fR,
+\fRsudoHost\fR
+and
+\fRsudoCommand\fR.
+.PP
+The following example allows users in group wheel to run any command
+on any host via
+\fBsudo\fR:
+.nf
+.sp
+.RS 4n
+dn: cn=%wheel,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoCommand: ALL
+.RE
+.fi
+.SS "Anatomy of LDAP sudoers lookup"
+When looking up a sudoer using LDAP there are only two or three
+LDAP queries per invocation.
+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
+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
+non-Unix groups and checks to see if the user belongs to any of them.
+.PP
+If timed entries are enabled with the
+\fBSUDOERS_TIMED\fR
+configuration directive, the LDAP queries include a sub-filter that
+limits retrieval to entries that satisfy the time constraints, if any.
+.PP
+If the
+\fBNETGROUP_BASE\fR
+configuration directive is present (see
+\fIConfiguring ldap.conf\fR
+below), queries are performed to determine
+the list of netgroups the user belongs to before the sudoers query.
+This makes it possible to include netgroups in the sudoers query
+string in the same manner as Unix groups.
+The third query mentioned above is not performed unless a group provider
+plugin is also configured.
+The actual LDAP queries performed by
+\fBsudo\fR
+are as follows:
+.TP 5n
+1.\&
+Match all
+\fRnisNetgroup\fR
+records with a
+\fRnisNetgroupTriple\fR
+containing the user, host and NIS domain.
+The query will match
+\fRnisNetgroupTriple\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
+that include the domain or for which there is no domain present.
+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.
+.TP 5n
+2.\&
+Repeated queries are performed to find any nested
+\fRnisNetgroup\fR
+records with a
+\fRmemberNisNetgroup\fR
+entry that refers to an already-matched record.
+.PP
+For sites with a large number of netgroups, using
+\fBNETGROUP_BASE\fR
+can significantly speed up
+\fBsudo\fR's
+execution time.
+.SS "Differences between LDAP and non-LDAP sudoers"
+One of the major differences between LDAP and file-based
+\fIsudoers\fR
+is that in LDAP,
+\fBsudo\fR-specific
+Aliases are not supported.
+.PP
+For the most part, there is little need for
+\fBsudo\fR-specific
+Aliases.
+Unix groups, non-Unix groups (via the
+\fIgroup_plugin\fR)
+or user netgroups can be used in place of User_Aliases and Runas_Aliases.
+Host netgroups can be used in place of Host_Aliases.
+Since groups and netgroups can also be stored in LDAP there is no real need for
+\fBsudo\fR-specific
+aliases.
+.PP
+There are also some subtle differences in the way sudoers is handled
+once in LDAP.
+Probably the biggest is that according to the RFC, LDAP ordering
+is arbitrary and you cannot expect that Attributes and Entries are
+returned in any specific order.
+.PP
+The order in which different entries are applied can be controlled
+using the
+\fRsudoOrder\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
+takes precedence.
+This is called paranoid behavior (not necessarily the most specific
+match).
+.PP
+Here is an example:
+.nf
+.sp
+.RS 4n
+# /etc/sudoers:
+# Allow all commands except shell
+johnny ALL=(root) ALL,!/bin/sh
+# Always allows all commands because ALL is matched last
+puddles ALL=(root) !/bin/sh,ALL
+
+# LDAP equivalent of johnny
+# Allows all commands except shell
+dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role1
+sudoUser: johnny
+sudoHost: ALL
+sudoCommand: ALL
+sudoCommand: !/bin/sh
+
+# LDAP equivalent of puddles
+# Notice that even though ALL comes last, it still behaves like
+# role1 since the LDAP code assumes the more paranoid configuration
+dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role2
+sudoUser: puddles
+sudoHost: ALL
+sudoCommand: !/bin/sh
+sudoCommand: ALL
+.RE
+.fi
+.PP
+Another difference is that it is not possible to use negation in a
+sudoUser, sudoRunAsUser or sudoRunAsGroup attribute.
+For example, the following attributes do not behave the way one might expect.
+.nf
+.sp
+.RS 4n
+# does not match all but joe
+# rather, does not match anyone
+sudoUser: !joe
+
+# does not match all but joe
+# rather, matches everyone including Joe
+sudoUser: ALL
+sudoUser: !joe
+.RE
+.fi
+.SS "Converting between file-based and LDAP sudoers"
+The
+cvtsudoers(1)
+utility can be used to convert between file-based and LDAP
+\fIsudoers\fR.
+However, there are features in the file-based sudoers that have
+no equivalent in LDAP-based sudoers (and vice versa).
+These cannot be converted automatically.
+.PP
+For example, a Cmnd_Alias in a
+\fIsudoers\fR
+file may be converted to a
+\fRsudoRole\fR
+that contains multiple commands.
+Multiple users and/or groups may be assigned to the
+\fRsudoRole\fR.
+.PP
+Also, host, user, runas and command-based
+\fRDefaults\fR
+entries are not supported.
+However, a
+\fRsudoRole\fR
+may contain one or more
+\fRsudoOption\fR
+attributes which can often serve the same purpose.
+.PP
+Consider the following
+\fIsudoers\fR
+lines:
+.nf
+.sp
+.RS 4n
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+Defaults!PAGERS noexec
+alice, bob ALL = ALL
+.RE
+.fi
+.PP
+In this example, alice and bob are allowed to run all commands, but
+the commands listed in PAGERS will have the noexec flag set,
+preventing shell escapes.
+.PP
+When converting this to LDAP, two sudoRole objects can be used:
+.nf
+.sp
+.RS 4n
+dn: cn=PAGERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: PAGERS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: /usr/bin/more
+sudoCommand: /usr/bin/pg
+sudoCommand: /usr/bin/less
+sudoOption: noexec
+sudoOrder: 900
+
+dn: cn=ADMINS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ADMINS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 100
+.RE
+.fi
+.PP
+In the LDAP version, the sudoOrder attribute is used to guarantee
+that the PAGERS sudoRole with
+\fInoexec\fR
+has precedence.
+Unlike the
+\fIsudoers\fR
+version, the LDAP version requires that all users for whom the restriction
+should apply be assigned to the PAGERS sudoRole.
+Using a Unix group or netgroup in PAGERS rather than listing each
+user would make this easier to maintain.
+.PP
+Per-user
+\fRDefaults\fR
+entries can be emulated by using one or more sudoOption attributes
+in a sudoRole.
+Consider the following
+\fIsudoers\fR
+lines:
+.nf
+.sp
+.RS 4n
+User_Alias ADMINS = john, sally
+Defaults:ADMINS !authenticate
+ADMINS ALL = (ALL:ALL) ALL
+.RE
+.fi
+.PP
+In this example, john and sally are allowed to run any command
+as any user or group.
+.PP
+When converting this to LDAP, we can use a Unix group instead
+of the User_Alias.
+.nf
+.sp
+.RS 4n
+dn: cn=admins,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: admins
+sudoUser: %admin
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+.RE
+.fi
+.PP
+This assumes that users john and sally are members of the
+\(lqadmins\(rq
+Unix group.
+.SS "Sudoers schema"
+In order to use
+\fBsudo\fR's
+LDAP support, the
+\fBsudo\fR
+schema must be
+installed on your LDAP server.
+In addition, be sure to index the
+\fRsudoUser\fR
+attribute.
+.PP
+The
+\fBsudo\fR
+distribution includes versions of the
+\fBsudoers\fR
+schema for multiple LDAP servers:
+.TP 6n
+\fIschema.OpenLDAP\fR
+OpenLDAP slapd and
+OpenBSD
+ldapd
+.TP 6n
+\fIschema.olcSudo\fR
+OpenLDAP slapd 2.3 and higher when on-line configuration is enabled
+.TP 6n
+\fIschema.iPlanet\fR
+Netscape-derived servers such as the iPlanet, Oracle,
+and 389 Directory Servers
+.TP 6n
+\fIschema.ActiveDirectory\fR
+Microsoft Active Directory
+.PP
+The schema in OpenLDAP format is also included in the
+\fIEXAMPLES\fR
+section.
+.SS "Configuring ldap.conf"
+Sudo reads the
+\fI@ldap_conf@\fR
+file for LDAP-specific configuration.
+Typically, this file is shared between different LDAP-aware clients.
+As such, most of the settings are not
+\fBsudo\fR-specific.
+Note that
+\fBsudo\fR
+parses
+\fI@ldap_conf@\fR
+itself and may support options that differ from those described in the
+system's
+ldap.conf(@mansectform@)
+manual.
+The path to
+\fIldap.conf\fR
+may be overridden via the
+\fIldap_conf\fR
+plugin argument in
+sudo.conf(@mansectform@).
+.PP
+Also note that on systems using the OpenLDAP libraries, default
+values specified in
+\fI/etc/openldap/ldap.conf\fR
+or the user's
+\fI.ldaprc\fR
+files are not used.
+.PP
+\fBsudo\fR
+supports a variety of LDAP library implementations, including
+OpenLDAP, Netscape-derived (also used by Solaris and HP-UX), and
+IBM LDAP (aka Tivoli).
+Some options are specific to certain LDAP implementations or have
+implementation-specific behavior.
+These differences are noted below where applicable.
+.PP
+Only those options explicitly listed in
+\fI@ldap_conf@\fR
+as being supported by
+\fBsudo\fR
+are honored.
+Configuration options are listed below in upper case but are parsed
+in a case-independent manner.
+.PP
+Lines beginning with a pound sign
+(\(oq#\(cq)
+are ignored.
+Leading white space is removed from the beginning of lines.
+.TP 6n
+\fBBIND_TIMELIMIT\fR \fIseconds\fR
+The
+\fBBIND_TIMELIMIT\fR
+parameter specifies the amount of time, in seconds, to wait while trying
+to connect to an LDAP server.
+If multiple
+\fBURI\fRs
+or
+\fBHOST\fRs
+are specified, this is the amount of time to wait before trying
+the next one in the list.
+.TP 6n
+\fBBINDDN\fR \fIDN\fR
+The
+\fBBINDDN\fR
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing LDAP operations.
+If not specified, LDAP operations are performed with an anonymous identity.
+By default, most LDAP servers will allow anonymous access.
+.TP 6n
+\fBBINDPW\fR \fIsecret\fR
+The
+\fBBINDPW\fR
+parameter specifies the password to use when performing LDAP operations.
+This is typically used in conjunction with the
+\fBBINDDN\fR
+parameter.
+The
+\fIsecret\fR
+may be a plain text password or a base64-encoded string with a
+\(lqbase64:\(rq
+prefix.
+For example:
+.nf
+.sp
+.RS 10n
+BINDPW base64:dGVzdA==
+.RE
+.fi
+.RS 6n
+.sp
+If a plain text password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+(\(oq#\(cq)
+and the escaping of special characters with a backslash
+(\(oq\e\(cq)
+is not supported.
+.RE
+.TP 6n
+\fBDEREF\fR \fInever/searching/finding/always\fR
+How alias dereferencing is to be performed when searching.
+See the
+ldap.conf(@mansectform@)
+manual for a full description of this option.
+.TP 6n
+\fBHOST\fR \fIname[:port] ...\fR
+If no
+\fBURI\fR
+is specified (see below), the
+\fBHOST\fR
+parameter specifies a white space-delimited list of LDAP servers to connect to.
+Each host may include an optional
+\fIport\fR
+separated by a colon
+(\(oq:\&\(cq).
+The
+\fBHOST\fR
+parameter is deprecated in favor of the
+\fBURI\fR
+specification and is included for backward compatibility only.
+.TP 6n
+\fBKRB5_CCNAME\fR \fIfile name\fR
+The path to the Kerberos 5 credential cache to use when authenticating
+with the remote server.
+.sp
+This option is only relevant when using SASL authentication (see below).
+.TP 6n
+\fBLDAP_VERSION\fR \fInumber\fR
+The version of the LDAP protocol to use when connecting to the server.
+The default value is protocol version 3.
+.TP 6n
+\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.
+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
+object containing a
+\fRsudoUser\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
+object by its
+\fRnisNetgroupTriple\fR
+member.
+OpenLDAP's
+\fBslapd\fR
+requires the following change to the
+\fRnisNetgroupTriple\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 )
+.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
+or
+\fR(&(attribute=value)(attribute2=value2))\fR.
+The default search filter is:
+\fRobjectClass=nisNetgroup\fR.
+If
+\fIldap_filter\fR
+is omitted, no search filter will be used.
+.sp
+This option is only used when querying netgroups directly via LDAP.
+.TP 6n
+\fBNETWORK_TIMEOUT\fR \fIseconds\fR
+An alias for
+\fBBIND_TIMELIMIT\fR
+provided for OpenLDAP compatibility.
+.TP 6n
+\fBPORT\fR \fIport_number\fR
+If no
+\fBURI\fR
+is specified, the
+\fBPORT\fR
+parameter specifies the default port to connect to on the LDAP server if a
+\fBHOST\fR
+parameter does not specify the port itself.
+If no
+\fBPORT\fR
+parameter is used, the default is port 389 for LDAP and port 636 for LDAP
+over TLS (SSL).
+The
+\fBPORT\fR
+parameter is deprecated in favor of the
+\fBURI\fR
+specification and is included for backward compatibility only.
+.TP 6n
+\fBROOTBINDDN\fR \fIDN\fR
+The
+\fBROOTBINDDN\fR
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing privileged LDAP operations, such as
+\fIsudoers\fR
+queries.
+The password corresponding to the identity should be stored in the
+or the path specified by the
+\fIldap_secret\fR
+plugin argument in
+sudo.conf(@mansectform@),
+which defaults to
+\fI@ldap_secret@\fR.
+If no
+\fBROOTBINDDN\fR
+is specified, the
+\fBBINDDN\fR
+identity is used (if any).
+.TP 6n
+\fBROOTUSE_SASL\fR \fIon/true/yes/off/false/no\fR
+Enable
+\fBROOTUSE_SASL\fR
+to enable SASL authentication when connecting
+to an LDAP server from a privileged process, such as
+\fBsudo\fR.
+.TP 6n
+\fBSASL_AUTH_ID\fR \fIidentity\fR
+The SASL user name to use when connecting to the LDAP server.
+By default,
+\fBsudo\fR
+will use an anonymous connection.
+.sp
+This option is only relevant when using SASL authentication.
+.TP 6n
+\fBSASL_MECH\fR \fImechanisms\fR
+A white space-delimited list of SASL authentication mechanisms to use.
+By default,
+\fBsudo\fR
+will use
+\fRGSSAPI\fR
+authentication.
+.TP 6n
+\fBSASL_SECPROPS\fR \fInone/properties\fR
+SASL security properties or
+\fInone\fR
+for no properties.
+See the SASL programmer's manual for details.
+.sp
+This option is only relevant when using SASL authentication.
+.TP 6n
+\fBSSL\fR \fIon/true/yes/off/false/no\fR
+If the
+\fBSSL\fR
+parameter is set to
+\fRon\fR,
+\fRtrue\fR
+\fRor\fR
+\fRyes\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
+\fBSSL\fR \fIstart_tls\fR
+If the
+\fBSSL\fR
+parameter is set to
+\fRstart_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
+communications.
+This parameter is only supported by LDAP servers that honor the
+\fIstart_tls\fR
+extension, such as the OpenLDAP and IBM Tivoli Directory servers.
+.TP 6n
+\fBSUDOERS_BASE\fR \fIbase\fR
+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.
+Multiple
+\fBSUDOERS_BASE\fR
+lines may be specified, in which case they are queried in the order specified.
+.TP 6n
+\fBSUDOERS_DEBUG\fR \fIdebug_level\fR
+This sets the debug level for
+\fBsudo\fR
+LDAP queries.
+Debugging information is printed to the standard error.
+A value of 1 results in a moderate amount of debugging information.
+A value of 2 shows the results of the matches themselves.
+This parameter should not be set in a production environment as the
+extra information is likely to confuse users.
+.sp
+The
+\fBSUDOERS_DEBUG\fR
+parameter is deprecated and will be removed in a future release.
+The same information is now logged via the
+\fBsudo\fR
+debugging framework using the
+\(lqldap\(rq
+subsystem at priorities
+\fIdiag\fR
+and
+\fIinfo\fR
+for
+\fIdebug_level\fR
+values 1 and 2 respectively.
+See the
+sudo.conf(@mansectform@)
+manual for details on how to configure
+\fBsudo\fR
+debugging.
+.TP 6n
+\fBSUDOERS_SEARCH_FILTER\fR \fIldap_filter\fR
+An LDAP filter which is used to restrict the set of records returned
+when performing a
+\fBsudo\fR
+LDAP query.
+Typically, this is of the
+form
+\fRattribute=value\fR
+or
+\fR(&(attribute=value)(attribute2=value2))\fR.
+The default search filter is:
+\fRobjectClass=sudoRole\fR.
+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
+and
+\fRsudoNotAfter\fR
+attributes that implement time-dependent sudoers entries.
+.TP 6n
+\fBTIMELIMIT\fR \fIseconds\fR
+The
+\fBTIMELIMIT\fR
+parameter specifies the amount of time, in seconds, to wait for a
+response to an LDAP query.
+.TP 6n
+\fBTIMEOUT\fR \fIseconds\fR
+The
+\fBTIMEOUT\fR
+parameter specifies the amount of time, in seconds, to wait for a
+response from the various LDAP APIs.
+.TP 6n
+\fBTLS_CACERT\fR \fIfile name\fR
+An alias for
+\fBTLS_CACERTFILE\fR
+for OpenLDAP compatibility.
+.TP 6n
+\fBTLS_CACERTFILE\fR \fIfile name\fR
+The path to a certificate authority bundle which contains the certificates
+for all the Certificate Authorities the client knows to be valid, e.g.,
+\fI/etc/ssl/ca-bundle.pem\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+Netscape-derived LDAP libraries use the same certificate
+database for CA and client certificates (see
+\fBTLS_CERT\fR).
+.TP 6n
+\fBTLS_CACERTDIR\fR \fIdirectory\fR
+Similar to
+\fBTLS_CACERTFILE\fR
+but instead of a file, it is a directory containing individual
+Certificate Authority certificates, e.g.,
+\fI/etc/ssl/certs\fR.
+The directory specified by
+\fBTLS_CACERTDIR\fR
+is checked after
+\fBTLS_CACERTFILE\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+.TP 6n
+\fBTLS_CERT\fR \fIfile name\fR
+The path to a file containing the client certificate which can
+be used to authenticate the client to the LDAP server.
+The certificate type depends on the LDAP libraries used.
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+OpenLDAP:
+\fRtls_cert /etc/ssl/client_cert.pem\fR
+.PD
+.TP 6n
+Netscape-derived:
+\fRtls_cert /var/ldap/cert7.db\fR
+.TP 6n
+IBM LDAP:
+Unused, the key database specified by
+\fBTLS_KEY\fR
+contains both keys and certificates.
+.PP
+When using Netscape-derived libraries, this file may also contain
+Certificate Authority certificates.
+.RE
+.TP 6n
+\fBTLS_CHECKPEER\fR \fIon/true/yes/off/false/no\fR
+If enabled,
+\fBTLS_CHECKPEER\fR
+will cause the LDAP server's TLS certificated to be verified.
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+\fBsudo\fR
+will be unable to connect to it.
+If
+\fBTLS_CHECKPEER\fR
+is disabled, no check is made.
+Note that disabling the check creates an opportunity for man-in-the-middle
+attacks since the server's identity will not be authenticated.
+If possible, the CA's certificate should be installed locally so it can
+be verified.
+.sp
+This option is not supported by the IBM LDAP libraries.
+.TP 6n
+\fBTLS_KEY\fR \fIfile name\fR
+The path to a file containing the private key which matches the
+certificate specified by
+\fBTLS_CERT\fR.
+The private key must not be password-protected.
+The key type depends on the LDAP libraries used.
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+OpenLDAP:
+\fRtls_key /etc/ssl/client_key.pem\fR
+.PD
+.TP 6n
+Netscape-derived:
+\fRtls_key /var/ldap/key3.db\fR
+.TP 6n
+IBM LDAP:
+\fRtls_key /usr/ldap/ldapkey.kdb\fR
+.PP
+When using IBM LDAP libraries, this file may also contain
+Certificate Authority and client certificates and may be encrypted.
+.RE
+.TP 6n
+\fBTLS_CIPHERS\fR \fIcipher list\fR
+The
+\fBTLS_CIPHERS\fR
+parameter allows the administer to restrict which encryption algorithms
+may be used for TLS (SSL) connections.
+See the OpenLDAP or IBM Tivoli Directory Server manual for a list of valid
+ciphers.
+.sp
+This option is not supported by Netscape-derived libraries.
+.TP 6n
+\fBTLS_KEYPW\fR \fIsecret\fR
+The
+\fBTLS_KEYPW\fR
+contains the password used to decrypt the key database on clients
+using the IBM LDAP library.
+The
+\fIsecret\fR
+may be a plain text password or a base64-encoded string with a
+\(lqbase64:\(rq
+prefix.
+For example:
+.nf
+.sp
+.RS 10n
+TLS_KEYPW base64:dGVzdA==
+.RE
+.fi
+.RS 6n
+.sp
+If a plain text password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+(\(oq#\(cq)
+and the escaping of special characters with a backslash
+(\(oq\e\(cq)
+is not supported.
+If this option is used,
+\fI@ldap_conf@\fR
+must not be world-readable to avoid exposing the password.
+Alternately, a
+\fIstash file\fR
+can be used to store the password in encrypted form (see below).
+.sp
+If no
+\fBTLS_KEYPW\fR
+is specified, a
+\fIstash file\fR
+will be used if it exists.
+The
+\fIstash file\fR
+must have the same path as the file specified by
+\fBTLS_KEY\fR,
+but use a
+\fR.sth\fR
+file extension instead of
+\fR.kdb\fR,
+e.g.,
+\fRldapkey.sth\fR.
+The default
+\fRldapkey.kdb\fR
+that ships with the IBM Tivoli Directory Server is encrypted with the password
+\fRssl_password\fR.
+The
+\fIgsk8capicmd\fR
+utility can be used to manage the key database and create a
+\fIstash file\fR.
+.sp
+This option is only supported by the IBM LDAP libraries.
+.RE
+.TP 6n
+\fBTLS_REQCERT\fR \fIlevel\fR
+The
+\fBTLS_REQCERT\fR
+parameter controls how the LDAP server's TLS certificated will be
+verified (if at all).
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+\fBsudo\fR
+will be unable to connect to it.
+The following
+\fIlevel\fR
+values are supported:
+.RS 10n
+.TP 10n
+never
+The server certificate will not be requested or checked.
+.TP 10n
+allow
+The server certificate will be requested.
+A missing or invalid certificate is ignored and not considered an error.
+.TP 10n
+try
+The server certificate will be requested.
+A missing certificate is ignored but an invalid certificate will
+result in a connection error.
+.TP 10n
+demand | \fIhard\fR
+The server certificate will be requested.
+A missing or invalid certificate will result in a connection error.
+This is the default behavior.
+.RE
+.RS 6n
+.sp
+This option is only supported by the OpenLDAP libraries.
+Other LDAP libraries only support the
+\fBTLS_CHECKPEER\fR
+parameter.
+.RE
+.TP 6n
+\fBTLS_RANDFILE\fR \fIfile name\fR
+The
+\fBTLS_RANDFILE\fR
+parameter specifies the path to an entropy source for systems that lack
+a random device.
+It is generally used in conjunction with
+\fIprngd\fR
+or
+\fIegd\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+.TP 6n
+\fBURI\fR \fIldap[s]://[hostname[:port]] ...\fR
+Specifies a white space-delimited list of one or more URIs describing
+the LDAP server(s) to connect to.
+The
+\fIprotocol\fR
+may be either
+\fIldap\fR
+\fIldaps\fR,
+the latter being for servers that support TLS (SSL) encryption.
+If no
+\fIport\fR
+is specified, the default is port 389 for
+\fRldap://\fR
+or port 636 for
+\fRldaps://\fR.
+If no
+\fIhostname\fR
+is specified,
+\fBsudo\fR
+will connect to
+\fIlocalhost\fR.
+Multiple
+\fBURI\fR
+lines are treated identically to a
+\fBURI\fR
+line containing multiple entries.
+Only systems using the OpenSSL libraries support the mixing of
+\fRldap://\fR
+and
+\fRldaps://\fR
+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.
+.TP 6n
+\fBUSE_SASL\fR \fIon/true/yes/off/false/no\fR
+Enable
+\fBUSE_SASL\fR
+for LDAP servers that support SASL authentication.
+.TP 6n
+\fBROOTSASL_AUTH_ID\fR \fIidentity\fR
+The SASL user name to use when
+\fBROOTUSE_SASL\fR
+is enabled.
+.PP
+See the
+\fIldap.conf\fR
+entry in the
+\fIEXAMPLES\fR
+section.
+.SS "Configuring nsswitch.conf"
+Unless it is disabled at build time,
+\fBsudo\fR
+consults the Name Service Switch file,
+\fI@nsswitch_conf@\fR,
+to specify the
+\fIsudoers\fR
+search order.
+Sudo looks for a line beginning with
+\fRsudoers\fR:
+and uses this to determine the search order.
+Note that
+\fBsudo\fR
+does
+not stop searching after the first match and later matches take
+precedence over earlier ones.
+The following sources are recognized:
+.PP
+.RS 4n
+.PD 0
+.TP 10n
+files
+read sudoers from
+\fI@sysconfdir@/sudoers\fR
+.TP 10n
+ldap
+read sudoers from LDAP
+.RE
+.PD
+.PP
+In addition, the entry
+\fR[NOTFOUND=return]\fR
+will short-circuit the search if the user was not found in the
+preceding source.
+.PP
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.nf
+.sp
+.RS 4n
+sudoers: ldap files
+.RE
+.fi
+.PP
+The local
+\fIsudoers\fR
+file can be ignored completely by using:
+.nf
+.sp
+.RS 4n
+sudoers: ldap
+.RE
+.fi
+.PP
+If the
+\fI@nsswitch_conf@\fR
+file is not present or there is no sudoers line, the following
+default is assumed:
+.nf
+.sp
+.RS 4n
+sudoers: files
+.RE
+.fi
+.PP
+Note that
+\fI@nsswitch_conf@\fR
+is supported even when the underlying operating system does not use
+an nsswitch.conf file, except on AIX (see below).
+.SS "Configuring netsvc.conf"
+On AIX systems, the
+\fI@netsvc_conf@\fR
+file is consulted instead of
+\fI@nsswitch_conf@\fR.
+\fBsudo\fR
+simply treats
+\fInetsvc.conf\fR
+as a variant of
+\fInsswitch.conf\fR;
+information in the previous section unrelated to the file format
+itself still applies.
+.PP
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.nf
+.sp
+.RS 4n
+sudoers = ldap, files
+.RE
+.fi
+.PP
+The local
+\fIsudoers\fR
+file can be ignored completely by using:
+.nf
+.sp
+.RS 4n
+sudoers = ldap
+.RE
+.fi
+.PP
+To treat LDAP as authoritative and only use the local sudoers file
+if the user is not present in LDAP, use:
+.nf
+.sp
+.RS 4n
+sudoers = ldap = auth, files
+.RE
+.fi
+.PP
+Note that in the above example, the
+\fRauth\fR
+qualifier only affects user lookups; both LDAP and
+\fIsudoers\fR
+will be queried for
+\fRDefaults\fR
+entries.
+.PP
+If the
+\fI@netsvc_conf@\fR
+file is not present or there is no sudoers line, the following
+default is assumed:
+.nf
+.sp
+.RS 4n
+sudoers = files
+.RE
+.fi
+.SS "Integration with sssd"
+On systems with the
+\fISystem Security Services Daemon\fR
+(SSSD) and where
+\fBsudo\fR
+has been built with SSSD support,
+it is possible to use SSSD to cache LDAP
+\fIsudoers\fR
+rules.
+To use SSSD as the
+\fIsudoers\fR
+source, you should use
+\fRsss\fR
+instead of
+\fRldap\fR
+for the sudoers entry in
+\fI@nsswitch_conf@\fR.
+Note that the
+\fI@ldap_conf@\fR
+file is not used by the SSSD
+\fBsudo\fR
+back end.
+Please see
+sssd-sudo(@mansectform@)
+for more information on configuring
+\fBsudo\fR
+to work with SSSD.
+.SH "FILES"
+.TP 26n
+\fI@ldap_conf@\fR
+LDAP configuration file
+.TP 26n
+\fI@nsswitch_conf@\fR
+determines sudoers source order
+.TP 26n
+\fI@netsvc_conf@\fR
+determines sudoers source order on AIX
+.SH "EXAMPLES"
+.SS "Example ldap.conf"
+.nf
+.RS 2n
+# Either specify one or more URIs or one or more host:port pairs.
+# If neither is specified sudo will default to localhost, port 389.
+#
+#host ldapserver
+#host ldapserver1 ldapserver2:390
+#
+# Default port if host is specified without one, defaults to 389.
+#port 389
+#
+# URI will override the host and port settings.
+uri ldap://ldapserver
+#uri ldaps://secureldapserver
+#uri ldaps://secureldapserver ldap://ldapserver
+#
+# The amount of time, in seconds, to wait while trying to connect to
+# an LDAP server.
+bind_timelimit 30
+#
+# The amount of time, in seconds, to wait while performing an LDAP query.
+timelimit 30
+#
+# Must be set or sudo will ignore LDAP; may be specified multiple times.
+sudoers_base ou=SUDOers,dc=my-domain,dc=com
+#
+# verbose sudoers matching from ldap
+#sudoers_debug 2
+#
+# Enable support for time-based entries in sudoers.
+#sudoers_timed yes
+#
+# optional proxy credentials
+#binddn <who to search as>
+#bindpw <password>
+#rootbinddn <who to search as, uses /etc/ldap.secret for bindpw>
+#
+# LDAP protocol version, defaults to 3
+#ldap_version 3
+#
+# Define if you want to use an encrypted LDAP connection.
+# Typically, you must also set the port to 636 (ldaps).
+#ssl on
+#
+# Define if you want to use port 389 and switch to
+# encryption before the bind credentials are sent.
+# Only supported by LDAP servers that support the start_tls
+# extension such as OpenLDAP.
+#ssl start_tls
+#
+# Additional TLS options follow that allow tweaking of the
+# SSL/TLS connection.
+#
+#tls_checkpeer yes # verify server SSL certificate
+#tls_checkpeer no # ignore server SSL certificate
+#
+# If you enable tls_checkpeer, specify either tls_cacertfile
+# or tls_cacertdir. Only supported when using OpenLDAP.
+#
+#tls_cacertfile /etc/certs/trusted_signers.pem
+#tls_cacertdir /etc/certs
+#
+# For systems that don't have /dev/random
+# use this along with PRNGD or EGD.pl to seed the
+# random number pool to generate cryptographic session keys.
+# Only supported when using OpenLDAP.
+#
+#tls_randfile /etc/egd-pool
+#
+# You may restrict which ciphers are used. Consult your SSL
+# documentation for which options go here.
+# Only supported when using OpenLDAP.
+#
+#tls_ciphers <cipher-list>
+#
+# Sudo can provide a client certificate when communicating to
+# the LDAP server.
+# Tips:
+# * Enable both lines at the same time.
+# * Do not password protect the key file.
+# * Ensure the keyfile is only readable by root.
+#
+# For OpenLDAP:
+#tls_cert /etc/certs/client_cert.pem
+#tls_key /etc/certs/client_key.pem
+#
+# For Netscape-derived LDAP, tls_cert and tls_key may specify either
+# a directory, in which case the files in the directory must have the
+# default names (e.g., cert8.db and key4.db), or the path to the cert
+# and key files themselves. However, a bug in version 5.0 of the LDAP
+# SDK will prevent specific file names from working. For this reason
+# it is suggested that tls_cert and tls_key be set to a directory,
+# not a file name.
+#
+# The certificate database specified by tls_cert may contain CA certs
+# and/or the client's cert. If the client's cert is included, tls_key
+# should be specified as well.
+# For backward compatibility, "sslpath" may be used in place of tls_cert.
+#tls_cert /var/ldap
+#tls_key /var/ldap
+#
+# If using SASL authentication for LDAP (OpenSSL)
+# use_sasl yes
+# sasl_auth_id <SASL user name>
+# rootuse_sasl yes
+# rootsasl_auth_id <SASL user name for root access>
+# sasl_secprops none
+# krb5_ccname /etc/.ldapcache
+.RE
+.fi
+.SS "Sudoers schema for OpenLDAP"
+The following schema, in OpenLDAP format, is included with
+\fBsudo\fR
+source and binary distributions as
+\fIschema.OpenLDAP\fR.
+Simply copy
+it to the schema directory (e.g.,
+\fI/etc/openldap/schema\fR),
+add the proper
+\fRinclude\fR
+line in
+\fIslapd.conf\fR
+and restart
+\fBslapd\fR.
+Sites using the optional on-line configuration supported by OpenLDAP 2.3
+and higher should apply the
+\fIschema.olcSudo\fR
+file instead.
+.nf
+.sp
+.RS 2n
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 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 )
+
+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 )
+
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+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 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $
+ sudoOrder $ description )
+ )
+.RE
+.fi
+.SH "SEE ALSO"
+cvtsudoers(1),
+ldap.conf(@mansectform@),
+sssd-sudo(@mansectform@),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+Note that there are differences in the way that LDAP-based
+\fIsudoers\fR
+is parsed compared to file-based
+\fIsudoers\fR.
+See the
+\fIDifferences between LDAP and non-LDAP sudoers\fR
+section for more information.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers.ldap.mdoc.in b/doc/sudoers.ldap.mdoc.in
new file mode 100644
index 0000000..ac32bfa
--- /dev/null
+++ b/doc/sudoers.ldap.mdoc.in
@@ -0,0 +1,1588 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2003-2020 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.
+.\"
+.Dd October 29, 2020
+.Dt SUDOERS.LDAP @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers.ldap
+.Nd sudo LDAP configuration
+.Sh DESCRIPTION
+In addition to the standard
+.Em sudoers
+file,
+.Nm sudo
+may be configured
+via LDAP.
+This can be especially useful for synchronizing
+.Em sudoers
+in a large, distributed environment.
+.Pp
+Using LDAP for
+.Em sudoers
+has several benefits:
+.Bl -bullet -width 1n
+.It
+.Nm sudo
+no longer needs to read
+.Em sudoers
+in its entirety.
+When LDAP is used, there are only two or three LDAP queries per invocation.
+This makes it especially fast and particularly usable in LDAP environments.
+.It
+.Nm sudo
+no longer exits if there is a typo in
+.Em sudoers .
+It is not possible to load LDAP data into the server that does
+not conform to the sudoers schema, so proper syntax is guaranteed.
+It is still possible to have typos in a user or host name, but
+this will not prevent
+.Nm sudo
+from running.
+.It
+It is possible to specify per-entry options that override the global
+default options.
+.Pa @sysconfdir@/sudoers
+only supports default options and limited options associated with
+user/host/commands/aliases.
+The syntax is complicated and can be difficult for users to understand.
+Placing the options directly in the entry is more natural.
+.It
+The
+.Nm visudo
+program is no longer needed.
+.Nm visudo
+provides locking and syntax checking of the
+.Pa @sysconfdir@/sudoers
+file.
+Since LDAP updates are atomic, locking is no longer necessary.
+Because syntax is checked when the data is inserted into LDAP, there
+is no need for a specialized tool to check syntax.
+.El
+.Ss SUDOers LDAP container
+The
+.Em sudoers
+configuration is contained in the
+.Li ou=SUDOers
+LDAP container.
+.Pp
+Sudo first looks for the
+.Li cn=defaults
+entry in the SUDOers container.
+If found, the multi-valued
+.Li sudoOption
+attribute is parsed in the same manner as a global
+.Li Defaults
+line in
+.Pa @sysconfdir@/sudoers .
+In the following example, the
+.Ev SSH_AUTH_SOCK
+variable will be preserved in the environment for all users.
+.Bd -literal -offset 4n
+dn: cn=defaults,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: env_keep+=SSH_AUTH_SOCK
+.Ed
+.Pp
+The equivalent of a sudoer in LDAP is a
+.Li sudoRole .
+It consists of the following attributes:
+.Bl -tag -width 4n
+.It Sy sudoUser
+A user name, user-ID (prefixed with
+.Ql # ) ,
+Unix group name or ID (prefixed with
+.Ql %
+or
+.Ql %#
+respectively), user netgroup (prefixed with
+.Ql + ) ,
+or non-Unix group name or ID (prefixed with
+.Ql %:
+or
+.Ql %:#
+respectively).
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+Non-Unix group support is only available when an appropriate
+.Em group_plugin
+is defined in the global
+.Em defaults
+.Li sudoRole
+object.
+.It Sy sudoHost
+A host name, IP address, IP network, or host netgroup (prefixed with a
+.Ql + ) .
+The special value
+.Li 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
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Li sudoRole
+in which it resides will be ignored.
+Negated
+.Li 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,
+potentially including globbing characters (aka wild cards).
+If a command name is preceded by an exclamation point,
+.Ql \&! ,
+the user will be prohibited from running that command.
+.Pp
+The built-in command
+.Dq Li sudoedit
+is used to permit a user to run
+.Nm sudo
+with the
+.Fl e
+option (or as
+.Nm sudoedit ) .
+It may take command line arguments just as a normal command does.
+Note that
+.Dq Li sudoedit
+is a command built into
+.Nm sudo
+itself and must be specified in without a leading path.
+.Pp
+The special value
+.Li ALL
+will match any command.
+.Pp
+If a command name is prefixed with a SHA-2 digest, it will
+only be allowed if the digest matches.
+This may be useful in situations where the user invoking
+.Nm sudo
+has write access to the command or its parent directory.
+The following digest formats are supported: sha224, sha256, sha384 and sha512.
+The digest name must be followed by a colon
+.Pq Ql :\&
+and then the actual digest, in either hex or base64 format.
+For example, given the following value for sudoCommand:
+.Bd -literal -offset 4n
+sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ /bin/ls
+.Ed
+.Pp
+The user may only run
+.Pa /bin/ls
+if its sha224 digest matches the specified value.
+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
+in which it resides.
+.It Sy sudoRunAsUser
+A user name or uid (prefixed with
+.Ql # )
+that commands may be run as or a Unix group (prefixed with a
+.Ql % )
+or user netgroup (prefixed with a
+.Ql + )
+that contains a list of users that commands may be run as.
+The special value
+.Li ALL
+will match any user.
+If a
+.Li sudoRunAsUser
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Li sudoRole
+in which it resides will be ignored.
+If
+.Li sudoRunAsUser
+is specified but empty, it will match the invoking user.
+If neither
+.Li sudoRunAsUser
+nor
+.Li sudoRunAsGroup
+are present, the value of the
+.Em runas_default
+.Li sudoOption
+is used (defaults to
+.Li @runas_default@ ) .
+.Pp
+The
+.Li sudoRunAsUser
+attribute is only available in
+.Nm sudo
+versions
+1.7.0 and higher.
+Older versions of
+.Nm sudo
+use the
+.Li sudoRunAs
+attribute instead.
+Negated
+.Li sudoRunAsUser
+entries are only supported by version 1.8.26 or higher.
+.It Sy sudoRunAsGroup
+A Unix group or gid (prefixed with
+.Ql # )
+that commands may be run as.
+The special value
+.Li ALL
+will match any group.
+If a
+.Li sudoRunAsGroup
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Li sudoRole
+in which it resides will be ignored.
+.Pp
+The
+.Li sudoRunAsGroup
+attribute is only available in
+.Nm sudo
+versions
+1.7.0 and higher.
+Negated
+.Li sudoRunAsGroup
+entries are only supported by version 1.8.26 or higher.
+.It Sy sudoNotBefore
+A timestamp in the form
+.Li yyyymmddHHMMSSZ
+that can be used to provide a start date/time for when the
+.Li sudoRole
+will be valid.
+If multiple
+.Li sudoNotBefore
+entries are present, the earliest is used.
+Note that timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.Pp
+The
+.Li sudoNotBefore
+attribute is only available in
+.Nm sudo
+versions 1.7.5 and higher and must be explicitly enabled via the
+.Sy SUDOERS_TIMED
+option in
+.Pa @ldap_conf@ .
+.It Sy sudoNotAfter
+A timestamp in the form
+.Li yyyymmddHHMMSSZ
+that indicates an expiration date/time, after which the
+.Li sudoRole
+will no longer be valid.
+If multiple
+.Li sudoNotAfter
+entries are present, the last one is used.
+Note that timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.Pp
+The
+.Li sudoNotAfter
+attribute is only available in
+.Nm sudo
+versions
+1.7.5 and higher and must be explicitly enabled via the
+.Sy SUDOERS_TIMED
+option in
+.Pa @ldap_conf@ .
+.It Sy sudoOrder
+The
+.Li sudoRole
+entries retrieved from the LDAP directory have no inherent order.
+The
+.Li 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
+attribute is chosen.
+This corresponds to the
+.Dq last match
+behavior of the sudoers file.
+If the
+.Li sudoOrder
+attribute is not present, a value of 0 is assumed.
+.Pp
+The
+.Li sudoOrder
+attribute is only available in
+.Nm sudo
+versions 1.7.5 and higher.
+.El
+.Pp
+Each attribute listed above should contain a single value, but there
+may be multiple instances of each attribute type.
+A
+.Li sudoRole
+must contain at least one
+.Li sudoUser ,
+.Li sudoHost
+and
+.Li sudoCommand .
+.Pp
+The following example allows users in group wheel to run any command
+on any host via
+.Nm sudo :
+.Bd -literal -offset 4n
+dn: cn=%wheel,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoCommand: ALL
+.Ed
+.Ss Anatomy of LDAP sudoers lookup
+When looking up a sudoer using LDAP there are only two or three
+LDAP queries per invocation.
+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
+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
+non-Unix groups and checks to see if the user belongs to any of them.
+.Pp
+If timed entries are enabled with the
+.Sy SUDOERS_TIMED
+configuration directive, the LDAP queries include a sub-filter that
+limits retrieval to entries that satisfy the time constraints, if any.
+.Pp
+If the
+.Sy NETGROUP_BASE
+configuration directive is present (see
+.Sx Configuring ldap.conf
+below), queries are performed to determine
+the list of netgroups the user belongs to before the sudoers query.
+This makes it possible to include netgroups in the sudoers query
+string in the same manner as Unix groups.
+The third query mentioned above is not performed unless a group provider
+plugin is also configured.
+The actual LDAP queries performed by
+.Nm sudo
+are as follows:
+.Bl -enum
+.It
+Match all
+.Li nisNetgroup
+records with a
+.Li nisNetgroupTriple
+containing the user, host and NIS domain.
+The query will match
+.Li 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
+that include the domain or for which there is no domain present.
+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 .
+.It
+Repeated queries are performed to find any nested
+.Li nisNetgroup
+records with a
+.Li memberNisNetgroup
+entry that refers to an already-matched record.
+.El
+.Pp
+For sites with a large number of netgroups, using
+.Sy NETGROUP_BASE
+can significantly speed up
+.Nm sudo Ns 's
+execution time.
+.Ss Differences between LDAP and non-LDAP sudoers
+One of the major differences between LDAP and file-based
+.Em sudoers
+is that in LDAP,
+.Nm sudo Ns -specific
+Aliases are not supported.
+.Pp
+For the most part, there is little need for
+.Nm sudo Ns -specific
+Aliases.
+Unix groups, non-Unix groups (via the
+.Em group_plugin )
+or user netgroups can be used in place of User_Aliases and Runas_Aliases.
+Host netgroups can be used in place of Host_Aliases.
+Since groups and netgroups can also be stored in LDAP there is no real need for
+.Nm sudo Ns -specific
+aliases.
+.Pp
+There are also some subtle differences in the way sudoers is handled
+once in LDAP.
+Probably the biggest is that according to the RFC, LDAP ordering
+is arbitrary and you cannot expect that Attributes and Entries are
+returned in any specific order.
+.Pp
+The order in which different entries are applied can be controlled
+using the
+.Li 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
+takes precedence.
+This is called paranoid behavior (not necessarily the most specific
+match).
+.Pp
+Here is an example:
+.Bd -literal -offset 4n
+# /etc/sudoers:
+# Allow all commands except shell
+johnny ALL=(root) ALL,!/bin/sh
+# Always allows all commands because ALL is matched last
+puddles ALL=(root) !/bin/sh,ALL
+
+# LDAP equivalent of johnny
+# Allows all commands except shell
+dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role1
+sudoUser: johnny
+sudoHost: ALL
+sudoCommand: ALL
+sudoCommand: !/bin/sh
+
+# LDAP equivalent of puddles
+# Notice that even though ALL comes last, it still behaves like
+# role1 since the LDAP code assumes the more paranoid configuration
+dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role2
+sudoUser: puddles
+sudoHost: ALL
+sudoCommand: !/bin/sh
+sudoCommand: ALL
+.Ed
+.Pp
+Another difference is that it is not possible to use negation in a
+sudoUser, sudoRunAsUser or sudoRunAsGroup attribute.
+For example, the following attributes do not behave the way one might expect.
+.Bd -literal -offset 4n
+# does not match all but joe
+# rather, does not match anyone
+sudoUser: !joe
+
+# does not match all but joe
+# rather, matches everyone including Joe
+sudoUser: ALL
+sudoUser: !joe
+.Ed
+.Ss Converting between file-based and LDAP sudoers
+The
+.Xr cvtsudoers 1
+utility can be used to convert between file-based and LDAP
+.Em sudoers .
+However, there are features in the file-based sudoers that have
+no equivalent in LDAP-based sudoers (and vice versa).
+These cannot be converted automatically.
+.Pp
+For example, a Cmnd_Alias in a
+.Em sudoers
+file may be converted to a
+.Li sudoRole
+that contains multiple commands.
+Multiple users and/or groups may be assigned to the
+.Li sudoRole .
+.Pp
+Also, host, user, runas and command-based
+.Li Defaults
+entries are not supported.
+However, a
+.Li sudoRole
+may contain one or more
+.Li sudoOption
+attributes which can often serve the same purpose.
+.Pp
+Consider the following
+.Em sudoers
+lines:
+.Bd -literal -offset 4n
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+Defaults!PAGERS noexec
+alice, bob ALL = ALL
+.Ed
+.Pp
+In this example, alice and bob are allowed to run all commands, but
+the commands listed in PAGERS will have the noexec flag set,
+preventing shell escapes.
+.Pp
+When converting this to LDAP, two sudoRole objects can be used:
+.Bd -literal -offset 4n
+dn: cn=PAGERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: PAGERS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: /usr/bin/more
+sudoCommand: /usr/bin/pg
+sudoCommand: /usr/bin/less
+sudoOption: noexec
+sudoOrder: 900
+
+dn: cn=ADMINS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ADMINS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 100
+.Ed
+.Pp
+In the LDAP version, the sudoOrder attribute is used to guarantee
+that the PAGERS sudoRole with
+.Em noexec
+has precedence.
+Unlike the
+.Em sudoers
+version, the LDAP version requires that all users for whom the restriction
+should apply be assigned to the PAGERS sudoRole.
+Using a Unix group or netgroup in PAGERS rather than listing each
+user would make this easier to maintain.
+.Pp
+Per-user
+.Li Defaults
+entries can be emulated by using one or more sudoOption attributes
+in a sudoRole.
+Consider the following
+.Em sudoers
+lines:
+.Bd -literal -offset 4n
+User_Alias ADMINS = john, sally
+Defaults:ADMINS !authenticate
+ADMINS ALL = (ALL:ALL) ALL
+.Ed
+.Pp
+In this example, john and sally are allowed to run any command
+as any user or group.
+.Pp
+When converting this to LDAP, we can use a Unix group instead
+of the User_Alias.
+.Bd -literal -offset 4n
+dn: cn=admins,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: admins
+sudoUser: %admin
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+.Ed
+.Pp
+This assumes that users john and sally are members of the
+.Dq admins
+Unix group.
+.Ss Sudoers schema
+In order to use
+.Nm sudo Ns 's
+LDAP support, the
+.Nm sudo
+schema must be
+installed on your LDAP server.
+In addition, be sure to index the
+.Li sudoUser
+attribute.
+.Pp
+The
+.Nm sudo
+distribution includes versions of the
+.Nm sudoers
+schema for multiple LDAP servers:
+.Bl -tag -width 4n
+.It Pa schema.OpenLDAP
+OpenLDAP slapd and
+.Ox
+ldapd
+.It Pa schema.olcSudo
+OpenLDAP slapd 2.3 and higher when on-line configuration is enabled
+.It Pa schema.iPlanet
+Netscape-derived servers such as the iPlanet, Oracle,
+and 389 Directory Servers
+.It Pa schema.ActiveDirectory
+Microsoft Active Directory
+.El
+.Pp
+The schema in OpenLDAP format is also included in the
+.Sx EXAMPLES
+section.
+.Ss Configuring ldap.conf
+Sudo reads the
+.Pa @ldap_conf@
+file for LDAP-specific configuration.
+Typically, this file is shared between different LDAP-aware clients.
+As such, most of the settings are not
+.Nm sudo Ns -specific.
+Note that
+.Nm sudo
+parses
+.Pa @ldap_conf@
+itself and may support options that differ from those described in the
+system's
+.Xr ldap.conf @mansectform@
+manual.
+The path to
+.Pa ldap.conf
+may be overridden via the
+.Em ldap_conf
+plugin argument in
+.Xr sudo.conf @mansectform@ .
+.Pp
+Also note that on systems using the OpenLDAP libraries, default
+values specified in
+.Pa /etc/openldap/ldap.conf
+or the user's
+.Pa .ldaprc
+files are not used.
+.Pp
+.Nm sudo
+supports a variety of LDAP library implementations, including
+OpenLDAP, Netscape-derived (also used by Solaris and HP-UX), and
+IBM LDAP (aka Tivoli).
+Some options are specific to certain LDAP implementations or have
+implementation-specific behavior.
+These differences are noted below where applicable.
+.Pp
+Only those options explicitly listed in
+.Pa @ldap_conf@
+as being supported by
+.Nm sudo
+are honored.
+Configuration options are listed below in upper case but are parsed
+in a case-independent manner.
+.Pp
+Lines beginning with a pound sign
+.Pq Ql #
+are ignored.
+Leading white space is removed from the beginning of lines.
+.Bl -tag -width 4n
+.It Sy BIND_TIMELIMIT Ar seconds
+The
+.Sy BIND_TIMELIMIT
+parameter specifies the amount of time, in seconds, to wait while trying
+to connect to an LDAP server.
+If multiple
+.Sy URI Ns s
+or
+.Sy HOST Ns s
+are specified, this is the amount of time to wait before trying
+the next one in the list.
+.It Sy BINDDN Ar DN
+The
+.Sy BINDDN
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing LDAP operations.
+If not specified, LDAP operations are performed with an anonymous identity.
+By default, most LDAP servers will allow anonymous access.
+.It Sy BINDPW Ar secret
+The
+.Sy BINDPW
+parameter specifies the password to use when performing LDAP operations.
+This is typically used in conjunction with the
+.Sy BINDDN
+parameter.
+The
+.Ar secret
+may be a plain text password or a base64-encoded string with a
+.Dq base64:
+prefix.
+For example:
+.Bd -literal -offset 4n
+BINDPW base64:dGVzdA==
+.Ed
+.Pp
+If a plain text password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+.Pq Ql #
+and the escaping of special characters with a backslash
+.Pq Ql \e
+is not supported.
+.It Sy DEREF Ar never/searching/finding/always
+How alias dereferencing is to be performed when searching.
+See the
+.Xr ldap.conf @mansectform@
+manual for a full description of this option.
+.It Sy HOST Ar name[:port] ...
+If no
+.Sy URI
+is specified (see below), the
+.Sy HOST
+parameter specifies a white space-delimited list of LDAP servers to connect to.
+Each host may include an optional
+.Em port
+separated by a colon
+.Pq Ql :\& .
+The
+.Sy HOST
+parameter is deprecated in favor of the
+.Sy URI
+specification and is included for backward compatibility only.
+.It Sy KRB5_CCNAME Ar file name
+The path to the Kerberos 5 credential cache to use when authenticating
+with the remote server.
+.Pp
+This option is only relevant when using SASL authentication (see below).
+.It Sy LDAP_VERSION Ar number
+The version of the LDAP protocol to use when connecting to the server.
+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 .
+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
+object containing a
+.Li sudoUser
+that begins with a
+.Ql +
+prefix.
+The NIS schema used by some LDAP servers need a modification to
+support querying the
+.Li nisNetgroup
+object by its
+.Li nisNetgroupTriple
+member.
+OpenLDAP's
+.Sy slapd
+requires the following change to the
+.Li 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 )
+.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
+or
+.Li (&(attribute=value)(attribute2=value2)) .
+The default search filter is:
+.Li objectClass=nisNetgroup .
+If
+.Ar ldap_filter
+is omitted, no search filter will be used.
+.Pp
+This option is only used when querying netgroups directly via LDAP.
+.It Sy NETWORK_TIMEOUT Ar seconds
+An alias for
+.Sy BIND_TIMELIMIT
+provided for OpenLDAP compatibility.
+.It Sy PORT Ar port_number
+If no
+.Sy URI
+is specified, the
+.Sy PORT
+parameter specifies the default port to connect to on the LDAP server if a
+.Sy HOST
+parameter does not specify the port itself.
+If no
+.Sy PORT
+parameter is used, the default is port 389 for LDAP and port 636 for LDAP
+over TLS (SSL).
+The
+.Sy PORT
+parameter is deprecated in favor of the
+.Sy URI
+specification and is included for backward compatibility only.
+.It Sy ROOTBINDDN Ar DN
+The
+.Sy ROOTBINDDN
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing privileged LDAP operations, such as
+.Em sudoers
+queries.
+The password corresponding to the identity should be stored in the
+or the path specified by the
+.Em ldap_secret
+plugin argument in
+.Xr sudo.conf @mansectform@ ,
+which defaults to
+.Pa @ldap_secret@ .
+If no
+.Sy ROOTBINDDN
+is specified, the
+.Sy BINDDN
+identity is used (if any).
+.It Sy ROOTUSE_SASL Ar on/true/yes/off/false/no
+Enable
+.Sy ROOTUSE_SASL
+to enable SASL authentication when connecting
+to an LDAP server from a privileged process, such as
+.Nm sudo .
+.It Sy SASL_AUTH_ID Ar identity
+The SASL user name to use when connecting to the LDAP server.
+By default,
+.Nm sudo
+will use an anonymous connection.
+.Pp
+This option is only relevant when using SASL authentication.
+.It Sy SASL_MECH Ar mechanisms
+A white space-delimited list of SASL authentication mechanisms to use.
+By default,
+.Nm sudo
+will use
+.Dv GSSAPI
+authentication.
+.It Sy SASL_SECPROPS Ar none/properties
+SASL security properties or
+.Em none
+for no properties.
+See the SASL programmer's manual for details.
+.Pp
+This option is only relevant when using SASL authentication.
+.It Sy SSL Ar on/true/yes/off/false/no
+If the
+.Sy SSL
+parameter is set to
+.Li on ,
+.Li true
+.Li or
+.Li 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 ,
+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
+communications.
+This parameter is only supported by LDAP servers that honor the
+.Em start_tls
+extension, such as the OpenLDAP and IBM Tivoli Directory servers.
+.It Sy SUDOERS_BASE Ar base
+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 .
+Multiple
+.Sy SUDOERS_BASE
+lines may be specified, in which case they are queried in the order specified.
+.It Sy SUDOERS_DEBUG Ar debug_level
+This sets the debug level for
+.Nm sudo
+LDAP queries.
+Debugging information is printed to the standard error.
+A value of 1 results in a moderate amount of debugging information.
+A value of 2 shows the results of the matches themselves.
+This parameter should not be set in a production environment as the
+extra information is likely to confuse users.
+.Pp
+The
+.Sy SUDOERS_DEBUG
+parameter is deprecated and will be removed in a future release.
+The same information is now logged via the
+.Nm sudo
+debugging framework using the
+.Dq ldap
+subsystem at priorities
+.Em diag
+and
+.Em info
+for
+.Em debug_level
+values 1 and 2 respectively.
+See the
+.Xr sudo.conf @mansectform@
+manual for details on how to configure
+.Nm sudo
+debugging.
+.It Sy SUDOERS_SEARCH_FILTER Ar ldap_filter
+An LDAP filter which is used to restrict the set of records returned
+when performing a
+.Nm sudo
+LDAP query.
+Typically, this is of the
+form
+.Li attribute=value
+or
+.Li (&(attribute=value)(attribute2=value2)) .
+The default search filter is:
+.Li 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
+and
+.Li sudoNotAfter
+attributes that implement time-dependent sudoers entries.
+.It Sy TIMELIMIT Ar seconds
+The
+.Sy TIMELIMIT
+parameter specifies the amount of time, in seconds, to wait for a
+response to an LDAP query.
+.It Sy TIMEOUT Ar seconds
+The
+.Sy TIMEOUT
+parameter specifies the amount of time, in seconds, to wait for a
+response from the various LDAP APIs.
+.It Sy TLS_CACERT Ar file name
+An alias for
+.Sy TLS_CACERTFILE
+for OpenLDAP compatibility.
+.It Sy TLS_CACERTFILE Ar file name
+The path to a certificate authority bundle which contains the certificates
+for all the Certificate Authorities the client knows to be valid, e.g.,
+.Pa /etc/ssl/ca-bundle.pem .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+Netscape-derived LDAP libraries use the same certificate
+database for CA and client certificates (see
+.Sy TLS_CERT ) .
+.It Sy TLS_CACERTDIR Ar directory
+Similar to
+.Sy TLS_CACERTFILE
+but instead of a file, it is a directory containing individual
+Certificate Authority certificates, e.g.,
+.Pa /etc/ssl/certs .
+The directory specified by
+.Sy TLS_CACERTDIR
+is checked after
+.Sy TLS_CACERTFILE .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+.It Sy TLS_CERT Ar file name
+The path to a file containing the client certificate which can
+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
+.It Netscape-derived:
+.Li tls_cert /var/ldap/cert7.db
+.It IBM LDAP:
+Unused, the key database specified by
+.Sy TLS_KEY
+contains both keys and certificates.
+.El
+.Pp
+When using Netscape-derived libraries, this file may also contain
+Certificate Authority certificates.
+.It Sy TLS_CHECKPEER Ar on/true/yes/off/false/no
+If enabled,
+.Sy TLS_CHECKPEER
+will cause the LDAP server's TLS certificated to be verified.
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+.Nm sudo
+will be unable to connect to it.
+If
+.Sy TLS_CHECKPEER
+is disabled, no check is made.
+Note that disabling the check creates an opportunity for man-in-the-middle
+attacks since the server's identity will not be authenticated.
+If possible, the CA's certificate should be installed locally so it can
+be verified.
+.Pp
+This option is not supported by the IBM LDAP libraries.
+.It Sy TLS_KEY Ar file name
+The path to a file containing the private key which matches the
+certificate specified by
+.Sy TLS_CERT .
+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
+.It Netscape-derived:
+.Li tls_key /var/ldap/key3.db
+.It IBM LDAP:
+.Li tls_key /usr/ldap/ldapkey.kdb
+.El
+.Pp
+When using IBM LDAP libraries, this file may also contain
+Certificate Authority and client certificates and may be encrypted.
+.It Sy TLS_CIPHERS Ar cipher list
+The
+.Sy TLS_CIPHERS
+parameter allows the administer to restrict which encryption algorithms
+may be used for TLS (SSL) connections.
+See the OpenLDAP or IBM Tivoli Directory Server manual for a list of valid
+ciphers.
+.Pp
+This option is not supported by Netscape-derived libraries.
+.It Sy TLS_KEYPW Ar secret
+The
+.Sy TLS_KEYPW
+contains the password used to decrypt the key database on clients
+using the IBM LDAP library.
+The
+.Ar secret
+may be a plain text password or a base64-encoded string with a
+.Dq base64:
+prefix.
+For example:
+.Bd -literal -offset 4n
+TLS_KEYPW base64:dGVzdA==
+.Ed
+.Pp
+If a plain text password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+.Pq Ql #
+and the escaping of special characters with a backslash
+.Pq Ql \e
+is not supported.
+If this option is used,
+.Pa @ldap_conf@
+must not be world-readable to avoid exposing the password.
+Alternately, a
+.Em stash file
+can be used to store the password in encrypted form (see below).
+.Pp
+If no
+.Sy TLS_KEYPW
+is specified, a
+.Em stash file
+will be used if it exists.
+The
+.Em stash file
+must have the same path as the file specified by
+.Sy TLS_KEY ,
+but use a
+.Li .sth
+file extension instead of
+.Li .kdb ,
+e.g.,
+.Li ldapkey.sth .
+The default
+.Li ldapkey.kdb
+that ships with the IBM Tivoli Directory Server is encrypted with the password
+.Li ssl_password .
+The
+.Em gsk8capicmd
+utility can be used to manage the key database and create a
+.Em stash file .
+.Pp
+This option is only supported by the IBM LDAP libraries.
+.It Sy TLS_REQCERT Ar level
+The
+.Sy TLS_REQCERT
+parameter controls how the LDAP server's TLS certificated will be
+verified (if at all).
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+.Nm sudo
+will be unable to connect to it.
+The following
+.Ar level
+values are supported:
+.Bl -tag -width 8n -offset 4n
+.It never
+The server certificate will not be requested or checked.
+.It allow
+The server certificate will be requested.
+A missing or invalid certificate is ignored and not considered an error.
+.It try
+The server certificate will be requested.
+A missing certificate is ignored but an invalid certificate will
+result in a connection error.
+.It demand | Ar hard
+The server certificate will be requested.
+A missing or invalid certificate will result in a connection error.
+This is the default behavior.
+.El
+.Pp
+This option is only supported by the OpenLDAP libraries.
+Other LDAP libraries only support the
+.Sy TLS_CHECKPEER
+parameter.
+.It Sy TLS_RANDFILE Ar file name
+The
+.Sy TLS_RANDFILE
+parameter specifies the path to an entropy source for systems that lack
+a random device.
+It is generally used in conjunction with
+.Em prngd
+or
+.Em egd .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+.It Sy URI Ar ldap[s]://[hostname[:port]] ...
+Specifies a white space-delimited list of one or more URIs describing
+the LDAP server(s) to connect to.
+The
+.Em protocol
+may be either
+.Em ldap
+.Em ldaps ,
+the latter being for servers that support TLS (SSL) encryption.
+If no
+.Em port
+is specified, the default is port 389 for
+.Li ldap://
+or port 636 for
+.Li ldaps:// .
+If no
+.Em hostname
+is specified,
+.Nm sudo
+will connect to
+.Em localhost .
+Multiple
+.Sy URI
+lines are treated identically to a
+.Sy URI
+line containing multiple entries.
+Only systems using the OpenSSL libraries support the mixing of
+.Li ldap://
+and
+.Li 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.
+.It Sy USE_SASL Ar on/true/yes/off/false/no
+Enable
+.Sy USE_SASL
+for LDAP servers that support SASL authentication.
+.It Sy ROOTSASL_AUTH_ID Ar identity
+The SASL user name to use when
+.Sy ROOTUSE_SASL
+is enabled.
+.El
+.Pp
+See the
+.Pa ldap.conf
+entry in the
+.Sx EXAMPLES
+section.
+.Ss Configuring nsswitch.conf
+Unless it is disabled at build time,
+.Nm sudo
+consults the Name Service Switch file,
+.Pa @nsswitch_conf@ ,
+to specify the
+.Em sudoers
+search order.
+Sudo looks for a line beginning with
+.Li sudoers :
+and uses this to determine the search order.
+Note that
+.Nm sudo
+does
+not stop searching after the first match and later matches take
+precedence over earlier ones.
+The following sources are recognized:
+.Pp
+.Bl -tag -width 8n -offset 4n -compact
+.It files
+read sudoers from
+.Pa @sysconfdir@/sudoers
+.It ldap
+read sudoers from LDAP
+.El
+.Pp
+In addition, the entry
+.Li [NOTFOUND=return]
+will short-circuit the search if the user was not found in the
+preceding source.
+.Pp
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.Bd -literal -offset 4n
+sudoers: ldap files
+.Ed
+.Pp
+The local
+.Em sudoers
+file can be ignored completely by using:
+.Bd -literal -offset 4n
+sudoers: ldap
+.Ed
+.Pp
+If the
+.Pa @nsswitch_conf@
+file is not present or there is no sudoers line, the following
+default is assumed:
+.Bd -literal -offset 4n
+sudoers: files
+.Ed
+.Pp
+Note that
+.Pa @nsswitch_conf@
+is supported even when the underlying operating system does not use
+an nsswitch.conf file, except on AIX (see below).
+.Ss Configuring netsvc.conf
+On AIX systems, the
+.Pa @netsvc_conf@
+file is consulted instead of
+.Pa @nsswitch_conf@ .
+.Nm sudo
+simply treats
+.Pa netsvc.conf
+as a variant of
+.Pa nsswitch.conf ;
+information in the previous section unrelated to the file format
+itself still applies.
+.Pp
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.Bd -literal -offset 4n
+sudoers = ldap, files
+.Ed
+.Pp
+The local
+.Em sudoers
+file can be ignored completely by using:
+.Bd -literal -offset 4n
+sudoers = ldap
+.Ed
+.Pp
+To treat LDAP as authoritative and only use the local sudoers file
+if the user is not present in LDAP, use:
+.Bd -literal -offset 4n
+sudoers = ldap = auth, files
+.Ed
+.Pp
+Note that in the above example, the
+.Li auth
+qualifier only affects user lookups; both LDAP and
+.Em sudoers
+will be queried for
+.Li Defaults
+entries.
+.Pp
+If the
+.Pa @netsvc_conf@
+file is not present or there is no sudoers line, the following
+default is assumed:
+.Bd -literal -offset 4n
+sudoers = files
+.Ed
+.Ss Integration with sssd
+On systems with the
+.Em System Security Services Daemon
+(SSSD) and where
+.Nm sudo
+has been built with SSSD support,
+it is possible to use SSSD to cache LDAP
+.Em sudoers
+rules.
+To use SSSD as the
+.Em sudoers
+source, you should use
+.Li sss
+instead of
+.Li ldap
+for the sudoers entry in
+.Pa @nsswitch_conf@ .
+Note that the
+.Pa @ldap_conf@
+file is not used by the SSSD
+.Nm sudo
+back end.
+Please see
+.Xr sssd-sudo @mansectform@
+for more information on configuring
+.Nm sudo
+to work with SSSD.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @ldap_conf@
+LDAP configuration file
+.It Pa @nsswitch_conf@
+determines sudoers source order
+.It Pa @netsvc_conf@
+determines sudoers source order on AIX
+.El
+.Sh EXAMPLES
+.Ss Example ldap.conf
+.Bd -literal -offset 2n
+# Either specify one or more URIs or one or more host:port pairs.
+# If neither is specified sudo will default to localhost, port 389.
+#
+#host ldapserver
+#host ldapserver1 ldapserver2:390
+#
+# Default port if host is specified without one, defaults to 389.
+#port 389
+#
+# URI will override the host and port settings.
+uri ldap://ldapserver
+#uri ldaps://secureldapserver
+#uri ldaps://secureldapserver ldap://ldapserver
+#
+# The amount of time, in seconds, to wait while trying to connect to
+# an LDAP server.
+bind_timelimit 30
+#
+# The amount of time, in seconds, to wait while performing an LDAP query.
+timelimit 30
+#
+# Must be set or sudo will ignore LDAP; may be specified multiple times.
+sudoers_base ou=SUDOers,dc=my-domain,dc=com
+#
+# verbose sudoers matching from ldap
+#sudoers_debug 2
+#
+# Enable support for time-based entries in sudoers.
+#sudoers_timed yes
+#
+# optional proxy credentials
+#binddn <who to search as>
+#bindpw <password>
+#rootbinddn <who to search as, uses /etc/ldap.secret for bindpw>
+#
+# LDAP protocol version, defaults to 3
+#ldap_version 3
+#
+# Define if you want to use an encrypted LDAP connection.
+# Typically, you must also set the port to 636 (ldaps).
+#ssl on
+#
+# Define if you want to use port 389 and switch to
+# encryption before the bind credentials are sent.
+# Only supported by LDAP servers that support the start_tls
+# extension such as OpenLDAP.
+#ssl start_tls
+#
+# Additional TLS options follow that allow tweaking of the
+# SSL/TLS connection.
+#
+#tls_checkpeer yes # verify server SSL certificate
+#tls_checkpeer no # ignore server SSL certificate
+#
+# If you enable tls_checkpeer, specify either tls_cacertfile
+# or tls_cacertdir. Only supported when using OpenLDAP.
+#
+#tls_cacertfile /etc/certs/trusted_signers.pem
+#tls_cacertdir /etc/certs
+#
+# For systems that don't have /dev/random
+# use this along with PRNGD or EGD.pl to seed the
+# random number pool to generate cryptographic session keys.
+# Only supported when using OpenLDAP.
+#
+#tls_randfile /etc/egd-pool
+#
+# You may restrict which ciphers are used. Consult your SSL
+# documentation for which options go here.
+# Only supported when using OpenLDAP.
+#
+#tls_ciphers <cipher-list>
+#
+# Sudo can provide a client certificate when communicating to
+# the LDAP server.
+# Tips:
+# * Enable both lines at the same time.
+# * Do not password protect the key file.
+# * Ensure the keyfile is only readable by root.
+#
+# For OpenLDAP:
+#tls_cert /etc/certs/client_cert.pem
+#tls_key /etc/certs/client_key.pem
+#
+# For Netscape-derived LDAP, tls_cert and tls_key may specify either
+# a directory, in which case the files in the directory must have the
+# default names (e.g., cert8.db and key4.db), or the path to the cert
+# and key files themselves. However, a bug in version 5.0 of the LDAP
+# SDK will prevent specific file names from working. For this reason
+# it is suggested that tls_cert and tls_key be set to a directory,
+# not a file name.
+#
+# The certificate database specified by tls_cert may contain CA certs
+# and/or the client's cert. If the client's cert is included, tls_key
+# should be specified as well.
+# For backward compatibility, "sslpath" may be used in place of tls_cert.
+#tls_cert /var/ldap
+#tls_key /var/ldap
+#
+# If using SASL authentication for LDAP (OpenSSL)
+# use_sasl yes
+# sasl_auth_id <SASL user name>
+# rootuse_sasl yes
+# rootsasl_auth_id <SASL user name for root access>
+# sasl_secprops none
+# krb5_ccname /etc/.ldapcache
+.Ed
+.Ss Sudoers schema for OpenLDAP
+The following schema, in OpenLDAP format, is included with
+.Nm sudo
+source and binary distributions as
+.Pa schema.OpenLDAP .
+Simply copy
+it to the schema directory (e.g.,
+.Pa /etc/openldap/schema ) ,
+add the proper
+.Li include
+line in
+.Pa slapd.conf
+and restart
+.Nm slapd .
+Sites using the optional on-line configuration supported by OpenLDAP 2.3
+and higher should apply the
+.Pa schema.olcSudo
+file instead.
+.Bd -literal -offset 2n
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 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 )
+
+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 )
+
+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 )
+
+attributetype ( 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 )
+
+attributetype ( 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 )
+
+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 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $
+ sudoOrder $ description )
+ )
+.Ed
+.Sh SEE ALSO
+.Xr cvtsudoers 1 ,
+.Xr ldap.conf @mansectform@ ,
+.Xr sssd-sudo @mansectform@ ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+Note that there are differences in the way that LDAP-based
+.Em sudoers
+is parsed compared to file-based
+.Em sudoers .
+See the
+.Sx Differences between LDAP and non-LDAP sudoers
+section for more information.
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in
new file mode 100644
index 0000000..6bd08d9
--- /dev/null
+++ b/doc/sudoers.man.in
@@ -0,0 +1,6548 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2021
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.TH "SUDOERS" "@mansectform@" "January 8, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers\fR
+\- default sudo security policy plugin
+.SH "DESCRIPTION"
+The
+\fBsudoers\fR
+policy plugin determines a user's
+\fBsudo\fR
+privileges.
+It is the default
+\fBsudo\fR
+policy plugin.
+The policy is driven by
+the
+\fI@sysconfdir@/sudoers\fR
+file or, optionally in LDAP.
+The policy format is described in detail in the
+\fISUDOERS FILE FORMAT\fR
+section.
+For information on storing
+\fBsudoers\fR
+policy information
+in LDAP, please see
+sudoers.ldap(@mansectform@).
+.SS "Configuring sudo.conf for sudoers"
+\fBsudo\fR
+consults the
+sudo.conf(@mansectform@)
+file to determine which policy and I/O logging plugins to load.
+If no
+sudo.conf(@mansectform@)
+file is present, or if it contains no
+\fRPlugin\fR
+lines,
+\fBsudoers\fR
+will be used for policy decisions and I/O logging.
+To explicitly configure
+sudo.conf(@mansectform@)
+to use the
+\fBsudoers\fR
+plugin, the following configuration can be used.
+.nf
+.sp
+.RS 6n
+Plugin sudoers_audit sudoers.so
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+.RE
+.fi
+.PP
+Starting with
+\fBsudo\fR
+1.8.5, it is possible to specify optional arguments to the
+\fBsudoers\fR
+plugin in the
+sudo.conf(@mansectform@)
+file.
+Plugin arguments, if any, should be listed after the path to the plugin
+(i.e., after
+\fIsudoers.so\fR).
+The arguments are only effective for the plugin that opens (and parses) the
+\fIsudoers\fR
+file.
+.PP
+For
+\fBsudo\fR
+version 1.9.1 and higher, this is the
+\fIsudoers_audit\fR
+plugin.
+For older versions, it is the
+\fIsudoers_policy\fR
+plugin.
+Multiple arguments may be specified, separated by white space.
+For example:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_audit sudoers.so sudoers_mode=0400 error_recovery=false
+.RE
+.fi
+.PP
+The following plugin arguments are supported:
+.TP 10n
+error_recovery=bool
+The
+\fIerror_recovery\fR
+argument can be used to control whether
+\fBsudoers\fR
+should attempt to recover from syntax errors in the
+\fIsudoers\fR
+file.
+If set to
+\fItrue\fR
+(the default),
+\fBsudoers\fR
+will try to recover from a syntax error by discarding the portion
+of the line that contains the error until the end of the line.
+A value of
+\fIfalse\fR
+will disable error recovery.
+Prior to version 1.9.3, no error recovery was performed.
+.TP 10n
+ldap_conf=pathname
+The
+\fIldap_conf\fR
+argument can be used to override the default path to the
+\fIldap.conf\fR
+file.
+.TP 10n
+ldap_secret=pathname
+The
+\fIldap_secret\fR
+argument can be used to override the default path to the
+\fIldap.secret\fR
+file.
+.TP 10n
+sudoers_file=pathname
+The
+\fIsudoers_file\fR
+argument can be used to override the default path to the
+\fIsudoers\fR
+file.
+.TP 10n
+sudoers_uid=uid
+The
+\fIsudoers_uid\fR
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.TP 10n
+sudoers_gid=gid
+The
+\fIsudoers_gid\fR
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.TP 10n
+sudoers_mode=mode
+The
+\fIsudoers_mode\fR
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+please refer to its manual.
+.SS "User Authentication"
+The
+\fBsudoers\fR
+security policy requires that most users authenticate
+themselves before they can use
+\fBsudo\fR.
+A password is not required
+if the invoking user is root, if the target user is the same as the
+invoking user, or if the policy has disabled authentication for the
+user or command.
+Unlike
+su(1),
+when
+\fBsudoers\fR
+requires
+authentication, it validates the invoking user's credentials, not
+the target user's (or root's) credentials.
+This can be changed via
+the
+\fIrootpw\fR,
+\fItargetpw\fR
+and
+\fIrunaspw\fR
+flags, described later.
+.PP
+If a user who is not listed in the policy tries to run a command
+via
+\fBsudo\fR,
+mail is sent to the proper authorities.
+The address
+used for such mail is configurable via the
+\fImailto\fR
+Defaults entry
+(described later) and defaults to
+\fR@mailto@\fR.
+.PP
+Note that no mail will be sent if an unauthorized user tries to run
+\fBsudo\fR
+with the
+\fB\-l\fR
+or
+\fB\-v\fR
+option unless there is an authentication error and
+either the
+\fImail_always\fR
+or
+\fImail_badpass\fR
+flags are enabled.
+This allows users to
+determine for themselves whether or not they are allowed to use
+\fBsudo\fR.
+By default, all attempts to run
+\fBsudo\fR
+(successful or not)
+are logged, regardless of whether or not mail is sent.
+.PP
+If
+\fBsudo\fR
+is run by root and the
+\fRSUDO_USER\fR
+environment variable
+is set, the
+\fBsudoers\fR
+policy will use this value to determine who
+the actual user is.
+This can be used by a user to log commands
+through sudo even when a root shell has been invoked.
+It also
+allows the
+\fB\-e\fR
+option to remain useful even when invoked via a
+sudo-run script or program.
+Note, however, that the
+\fIsudoers\fR
+file lookup is still done for root, not the user specified by
+\fRSUDO_USER\fR.
+.PP
+\fBsudoers\fR
+uses per-user time stamp files for credential caching.
+Once a user has been authenticated, a record is written
+containing the user-ID that was used to authenticate, the
+terminal session ID, the start time of the session leader
+(or parent process) and a time stamp
+(using a monotonic clock if one is available).
+The user may then use
+\fBsudo\fR
+without a password for a short period of time
+(\fR@timeout@\fR
+minutes unless overridden by the
+\fItimestamp_timeout\fR
+option)
+\&.
+By default,
+\fBsudoers\fR
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+\fItimestamp_type\fR
+option can be used to select the type of time stamp record
+\fBsudoers\fR
+will use.
+.SS "Logging"
+By default,
+\fBsudoers\fR
+logs both successful and unsuccessful attempts (as well
+as errors).
+The
+\fIlog_allowed\fR
+and
+\fIlog_denied\fR
+flags can be used to control this behavior.
+Messages can be logged to
+syslog(3),
+a log file, or both.
+The default is to log to
+syslog(3)
+but this is configurable via the
+\fIsyslog\fR
+and
+\fIlogfile\fR
+settings.
+See
+\fILOG FORMAT\fR
+for a description of the log file format.
+.PP
+\fBsudoers\fR
+is also capable of running a command in a pseudo-terminal and logging all
+input and/or output.
+The standard input, standard output and standard error can be logged
+even when not associated with a terminal.
+I/O logging is not on by default but can be enabled using
+the
+\fIlog_input\fR
+and
+\fIlog_output\fR
+options as well as the
+\fRLOG_INPUT\fR
+and
+\fRLOG_OUTPUT\fR
+command tags.
+See
+\fII/O LOG FILES\fR
+for details on how I/O log files are stored.
+.PP
+Starting with version 1.9, the
+\fIlog_servers\fR
+setting may be used to send event and I/O log data to a remote server running
+\fBsudo_logsrvd\fR
+or another service that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.SS "Command environment"
+Since environment variables can influence program behavior,
+\fBsudoers\fR
+provides a means to restrict which variables from the user's
+environment are inherited by the command to be run.
+There are two
+distinct ways
+\fBsudoers\fR
+can deal with environment variables.
+.PP
+By default, the
+\fIenv_reset\fR
+flag is enabled.
+This causes commands
+to be executed with a new, minimal environment.
+On AIX (and Linux
+systems without PAM), the environment is initialized with the
+contents of the
+\fI/etc/environment\fR
+file.
+.if \n(LC \{\
+On
+BSD
+systems, if the
+\fIuse_loginclass\fR
+flag is enabled, the environment is initialized
+based on the
+\fIpath\fR
+and
+\fIsetenv\fR
+settings in
+\fI/etc/login.conf\fR.
+.\}
+The
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+environment variables are initialized based on the target user
+and the
+\fRSUDO_*\fR
+variables are set based on the invoking user.
+Additional variables, such as
+\fRDISPLAY\fR,
+\fRPATH\fR
+and
+\fRTERM\fR,
+are preserved from the invoking user's environment if permitted by the
+\fIenv_check\fR
+or
+\fIenv_keep\fR
+options.
+A few environment variables are treated specially.
+If the
+\fRPATH\fR
+and
+\fRTERM\fR
+variables are not preserved from the user's environment, they will be set
+to default values.
+The
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+are handled as a single entity.
+If one of them is preserved (or removed) from the user's environment,
+the other will be as well.
+If
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+are to be preserved but only one of them is present in the user's environment,
+the other will be set to the same value.
+This avoids an inconsistent environment where one of the variables
+describing the user name is set to the invoking user and one is
+set to the target user.
+Environment variables with a value beginning with
+\fR()\fR
+are removed unless both the name and value parts are matched by
+\fIenv_keep\fR
+or
+\fIenv_check\fR,
+as they may be interpreted as functions by the
+\fBbash\fR
+shell.
+Prior to version 1.8.11, such variables were always removed.
+.PP
+If, however, the
+\fIenv_reset\fR
+flag is disabled, any variables not
+explicitly denied by the
+\fIenv_check\fR
+and
+\fIenv_delete\fR
+options are allowed and their values are
+inherited from the invoking process.
+Prior to version 1.8.21, environment variables with a value beginning with
+\fR()\fR
+were always removed.
+Beginning with version 1.8.21, a pattern in
+\fIenv_delete\fR
+is used to match
+\fBbash\fR
+shell functions instead.
+Since it is not possible
+to block all potentially dangerous environment variables, use
+of the default
+\fIenv_reset\fR
+behavior is encouraged.
+.PP
+Environment variables specified by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR
+may include one or more
+\(oq*\(cq
+characters which will match zero or more characters.
+No other wildcard characters are supported.
+.PP
+By default, environment variables are matched by name.
+However, if the pattern includes an equal sign
+(\(oq=\&\(cq),
+both the variables name and value must match.
+For example, a
+\fBbash\fR
+shell function could be matched as follows:
+.nf
+.sp
+.RS 4n
+env_keep += "BASH_FUNC_my_func%%=()*"
+.RE
+.fi
+.PP
+Without the
+\(lq\fR=()*\fR\(rq
+suffix, this would not match, as
+\fBbash\fR
+shell functions are not preserved by default.
+.PP
+The complete list of environment variables that are preserved or removed,
+as modified by global Defaults parameters in
+\fIsudoers\fR,
+is displayed when
+\fBsudo\fR
+is run by root with the
+\fB\-V\fR
+option.
+Please note that the list of environment variables to remove
+varies based on the operating system
+\fBsudo\fR
+is running on.
+.PP
+Other
+\fBsudoers\fR
+options may influence the command environment, such as
+\fIalways_set_home\fR,
+\fIsecure_path\fR,
+\fIset_logname\fR,
+and
+\fIset_home\fR.
+.PP
+On systems that support PAM where the
+\fBpam_env\fR
+module is enabled for
+\fBsudo\fR,
+variables in the PAM environment may be merged in to the environment.
+If a variable in the PAM environment is already present in the
+user's environment, the value will only be overridden if the variable
+was not preserved by
+\fBsudoers\fR.
+When
+\fIenv_reset\fR
+is enabled, variables preserved from the invoking user's environment
+by the
+\fIenv_keep\fR
+list take precedence over those in the PAM environment.
+When
+\fIenv_reset\fR
+is disabled, variables present the invoking user's environment
+take precedence over those in the PAM environment unless they
+match a pattern in the
+\fIenv_delete\fR
+list.
+.PP
+Note that the dynamic linker on most operating systems will remove
+variables that can control dynamic linking from the environment of
+set-user-ID executables, including
+\fBsudo\fR.
+Depending on the operating
+system this may include
+\fR_RLD*\fR,
+\fRDYLD_*\fR,
+\fRLD_*\fR,
+\fRLDR_*\fR,
+\fRLIBPATH\fR,
+\fRSHLIB_PATH\fR,
+and others.
+These type of variables are
+removed from the environment before
+\fBsudo\fR
+even begins execution
+and, as such, it is not possible for
+\fBsudo\fR
+to preserve them.
+.PP
+As a special case, if the
+\fB\-i\fR
+option (initial login) is
+specified,
+\fBsudoers\fR
+will initialize the environment regardless
+of the value of
+\fIenv_reset\fR.
+The
+\fRDISPLAY\fR,
+\fRPATH\fR
+and
+\fRTERM\fR
+variables remain unchanged;
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRUSER\fR,
+and
+\fRLOGNAME\fR
+are set based on the target user.
+On AIX (and Linux
+systems without PAM), the contents of
+\fI/etc/environment\fR
+are also
+included.
+.if \n(LC \{\
+On
+BSD
+systems, if the
+\fIuse_loginclass\fR
+flag is
+enabled, the
+\fIpath\fR
+and
+\fIsetenv\fR
+variables in
+\fI/etc/login.conf\fR
+are also applied.
+.\}
+All other environment variables are removed unless permitted by
+\fIenv_keep\fR
+or
+\fIenv_check\fR,
+described above.
+.PP
+Finally, the
+\fIrestricted_env_file\fR
+and
+\fIenv_file\fR
+files are applied, if present.
+The variables in
+\fIrestricted_env_file\fR
+are applied first and are subject to the same restrictions as the
+invoking user's environment, as detailed above.
+The variables in
+\fIenv_file\fR
+are applied last and are not subject to these restrictions.
+In both cases, variables present in the files will only be set to
+their specified values if they would not conflict with an existing
+environment variable.
+.SH "SUDOERS FILE FORMAT"
+The
+\fIsudoers\fR
+file is composed of two types of entries: aliases
+(basically variables) and user specifications (which specify who
+may run what).
+.PP
+When multiple entries match for a user, they are applied in order.
+Where there are multiple matches, the last match is used (which is
+not necessarily the most specific match).
+.PP
+The
+\fIsudoers\fR
+file grammar will be described below in Extended Backus-Naur
+Form (EBNF).
+Don't despair if you are unfamiliar with EBNF; it is fairly simple,
+and the definitions below are annotated.
+.SS "Quick guide to EBNF"
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of
+\fIproduction rules\fR.
+E.g.,
+.PP
+\fRsymbol ::= definition\fR | \fRalternate1\fR | \fRalternate2 ...\fR
+.PP
+Each
+\fIproduction rule\fR
+references others and thus makes up a
+grammar for the language.
+EBNF also contains the following
+operators, which many readers will recognize from regular
+expressions.
+Do not, however, confuse them with
+\(lqwildcard\(rq
+characters, which have different meanings.
+.TP 6n
+\fR\&?\fR
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
+.TP 6n
+\fR*\fR
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
+.TP 6n
+\fR+\fR
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
+.PP
+Parentheses may be used to group symbols together.
+For clarity,
+we will use single quotes
+('')
+to designate what is a verbatim character string (as opposed to a symbol name).
+.SS "Aliases"
+There are four kinds of aliases:
+\fRUser_Alias\fR,
+\fRRunas_Alias\fR,
+\fRHost_Alias\fR
+and
+\fRCmnd_Alias\fR.
+Beginning with
+\fBsudo\fR
+1.9.0,
+\fRCmd_Alias\fR
+may be used in place of
+\fRCmnd_Alias\fR
+if desired.
+.nf
+.sp
+.RS 0n
+Alias ::= 'User_Alias' User_Alias_Spec (':' User_Alias_Spec)* |
+ 'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
+ 'Host_Alias' Host_Alias_Spec (':' Host_Alias_Spec)* |
+ 'Cmnd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
+ 'Cmd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
+
+User_Alias ::= NAME
+
+User_Alias_Spec ::= User_Alias '=' User_List
+
+Runas_Alias ::= NAME
+
+Runas_Alias_Spec ::= Runas_Alias '=' Runas_List
+
+Host_Alias ::= NAME
+
+Host_Alias_Spec ::= Host_Alias '=' Host_List
+
+Cmnd_Alias ::= NAME
+
+Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
+
+NAME ::= [A-Z]([A-Z][0-9]_)*
+.RE
+.fi
+.PP
+Each
+\fIalias\fR
+definition is of the form
+.nf
+.sp
+.RS 0n
+Alias_Type NAME = item1, item2, ...
+.RE
+.fi
+.PP
+where
+\fIAlias_Type\fR
+is one of
+\fRUser_Alias\fR,
+\fRRunas_Alias\fR,
+\fRHost_Alias\fR,
+or
+\fRCmnd_Alias\fR.
+A
+\fRNAME\fR
+is a string of uppercase letters, numbers,
+and underscore characters
+(\(oq_\(cq).
+A
+\fRNAME\fR
+\fBmust\fR
+start with an
+uppercase letter.
+It is possible to put several alias definitions
+of the same type on a single line, joined by a colon
+(\(oq:\&\(cq).
+E.g.,
+.nf
+.sp
+.RS 0n
+Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+.RE
+.fi
+.PP
+It is a syntax error to redefine an existing
+\fIalias\fR.
+It is possible to use the same name for
+\fIaliases\fR
+of different types, but this is not recommended.
+.PP
+The definitions of what constitutes a valid
+\fIalias\fR
+member follow.
+.nf
+.sp
+.RS 0n
+User_List ::= User |
+ User ',' User_List
+
+User ::= '!'* user name |
+ '!'* #uid |
+ '!'* %group |
+ '!'* %#gid |
+ '!'* +netgroup |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* User_Alias
+.RE
+.fi
+.PP
+A
+\fRUser_List\fR
+is made up of one or more user names, user-IDs
+(prefixed with
+\(oq#\(cq),
+system group names and IDs (prefixed with
+\(oq%\(cq
+and
+\(oq%#\(cq
+respectively), netgroups (prefixed with
+\(oq+\(cq),
+non-Unix group names and IDs (prefixed with
+\(oq%:\(cq
+and
+\(oq%:#\(cq
+respectively) and
+\fRUser_Alias\fRes.
+Each list item may be prefixed with zero or more
+\(oq\&!\(cq
+operators.
+An odd number of
+\(oq\&!\(cq
+operators negate the value of
+the item; an even number just cancel each other out.
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+.PP
+A
+\fRuser name\fR,
+\fRuid\fR,
+\fRgroup\fR,
+\fRgid\fR,
+\fRnetgroup\fR,
+\fRnonunix_group\fR
+or
+\fRnonunix_gid\fR
+may be enclosed in double quotes to avoid the
+need for escaping special characters.
+Alternately, special characters
+may be specified in escaped hex mode, e.g., \ex20 for space.
+When
+using double quotes, any prefix characters must be included inside
+the quotes.
+.PP
+The actual
+\fRnonunix_group\fR
+and
+\fRnonunix_gid\fR
+syntax depends on
+the underlying group provider plugin.
+For instance, the QAS AD plugin supports the following formats:
+.TP 3n
+\fB\(bu\fR
+Group in the same domain: "%:Group Name"
+.TP 3n
+\fB\(bu\fR
+Group in any domain: "%:Group Name@FULLY.QUALIFIED.DOMAIN"
+.TP 3n
+\fB\(bu\fR
+Group SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
+.PP
+See
+\fIGROUP PROVIDER PLUGINS\fR
+for more information.
+.PP
+Note that quotes around group names are optional.
+Unquoted strings must use a backslash
+(\(oq\e\(cq)
+to escape spaces and special characters.
+See
+\fIOther special characters and reserved words\fR
+for a list of
+characters that need to be escaped.
+.nf
+.sp
+.RS 0n
+Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
+
+Runas_Member ::= '!'* user name |
+ '!'* #uid |
+ '!'* %group |
+ '!'* %#gid |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* +netgroup |
+ '!'* Runas_Alias
+.RE
+.fi
+.PP
+A
+\fRRunas_List\fR
+is similar to a
+\fRUser_List\fR
+except that instead
+of
+\fRUser_Alias\fRes
+it can contain
+\fRRunas_Alias\fRes.
+Note that
+user names and groups are matched as strings.
+In other words, two users (groups) with the same user (group) ID
+are considered to be distinct.
+If you wish to match all user names with the same user-ID (e.g., root and
+toor), you can use a user-ID instead of a name (#0 in the example given).
+Note that the user-ID or group-ID specified in a
+\fRRunas_Member\fR
+need not be listed in the password or group database.
+.nf
+.sp
+.RS 0n
+Host_List ::= Host |
+ Host ',' Host_List
+
+Host ::= '!'* host name |
+ '!'* ip_addr |
+ '!'* network(/netmask)? |
+ '!'* +netgroup |
+ '!'* Host_Alias
+.RE
+.fi
+.PP
+A
+\fRHost_List\fR
+is made up of one or more host names, IP addresses,
+network numbers, netgroups (prefixed with
+\(oq+\(cq)
+and other aliases.
+Again, the value of an item may be negated with the
+\(oq\&!\(cq
+operator.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If you specify a network number without a netmask,
+\fBsudo\fR
+will query each of the local host's network interfaces and,
+if the network number corresponds to one of the hosts's network
+interfaces, will use the netmask of that interface.
+The netmask may be specified either in standard IP address notation
+(e.g., 255.255.255.0 or ffff:ffff:ffff:ffff::),
+or CIDR notation (number of bits, e.g., 24 or 64).
+A host name may include shell-style wildcards (see the
+\fIWildcards\fR
+section below),
+but unless the
+\fRhost name\fR
+command on your machine returns the fully
+qualified host name, you'll need to use the
+\fIfqdn\fR
+flag for wildcards to be useful.
+Note that
+\fBsudo\fR
+only inspects actual network interfaces; this means that IP address
+127.0.0.1 (localhost) will never match.
+Also, the host name
+\(lqlocalhost\(rq
+will only match if that is the actual host name, which is usually
+only the case for non-networked systems.
+.nf
+.sp
+.RS 0n
+digest ::= [A-Fa-f0-9]+ |
+ [A-Za-z0-9\e+/=]+
+
+Digest_Spec ::= "sha224" ':' digest |
+ "sha256" ':' digest |
+ "sha384" ':' digest |
+ "sha512" ':' digest
+
+Digest_List ::= Digest_Spec |
+ Digest_Spec ',' Digest_List
+
+Cmnd_List ::= Cmnd |
+ Cmnd ',' Cmnd_List
+
+command name ::= file name |
+ file name args |
+ file name '""'
+
+Edit_Spec ::= "sudoedit" file name+
+
+Cmnd ::= Digest_List? '!'* command name |
+ '!'* directory |
+ '!'* Edit_Spec |
+ '!'* Cmnd_Alias
+.RE
+.fi
+.PP
+A
+\fRCmnd_List\fR
+is a list of one or more command names, directories, and other aliases.
+A command name is a fully qualified file name which may include
+shell-style wildcards (see the
+\fIWildcards\fR
+section below).
+A simple file name allows the user to run the command with any
+arguments they wish.
+However, you may also specify command line arguments (including
+wildcards).
+Alternately, you can specify
+\fR\&""\fR
+to indicate that the command
+may only be run
+\fBwithout\fR
+command line arguments.
+A directory is a
+fully qualified path name ending in a
+\(oq/\(cq.
+When you specify a directory in a
+\fRCmnd_List\fR,
+the user will be able to run any file within that directory
+(but not in any sub-directories therein).
+.PP
+If a
+\fRCmnd\fR
+has associated command line arguments, then the arguments
+in the
+\fRCmnd\fR
+must match exactly those given by the user on the command line
+(or match the wildcards if there are any).
+Note that the following characters must be escaped with a
+\(oq\e\(cq
+if they are used in command arguments:
+\(oq,\&\(cq,
+\(oq:\&\(cq,
+\(oq=\&\(cq,
+\(oq\e\(cq.
+The built-in command
+\(lq\fRsudoedit\fR\(rq
+is used to permit a user to run
+\fBsudo\fR
+with the
+\fB\-e\fR
+option (or as
+\fBsudoedit\fR).
+It may take command line arguments just as a normal command does.
+Note that
+\(lq\fRsudoedit\fR\(rq
+is a command built into
+\fBsudo\fR
+itself and must be specified in the
+\fIsudoers\fR
+file
+\fBwithout\fR
+a leading path.
+If a leading path is present, for example
+\fI/usr/bin/sudoedit\fR,
+the path name will be silently converted to
+\(lq\fRsudoedit\fR\(rq.
+A fully-qualified path for
+\fBsudoedit\fR
+is treated as an error by
+\fBvisudo\fR.
+.PP
+A
+\fRcommand name\fR
+may be preceded by a
+\fRDigest_List\fR,
+a comma-separated list of one or more
+\fRDigest_Spec\fR
+entries.
+If a
+\fRDigest_List\fR
+is present, the command will only match successfully if it can be verified
+using one of the SHA-2 digests in the list.
+Starting with version 1.9.0, the
+\fBALL\fR
+reserved word can be used in conjunction with a
+\fRDigest_List\fR.
+The following digest formats are supported: sha224, sha256, sha384 and sha512.
+The string may be specified in either hex or base64 format
+(base64 is more compact).
+There are several utilities capable of generating SHA-2 digests in hex
+format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
+.PP
+For example, using openssl:
+.nf
+.sp
+.RS 0n
+$ openssl dgst -sha224 /bin/ls
+SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
+.RE
+.fi
+.PP
+It is also possible to use openssl to generate base64 output:
+.nf
+.sp
+.RS 0n
+$ openssl dgst -binary -sha224 /bin/ls | openssl base64
+EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
+.RE
+.fi
+.PP
+Warning, if the user has write access to the command itself (directly or via a
+\fBsudo\fR
+command), it may be possible for the user to replace the command after the
+digest check has been performed but before the command is executed.
+A similar race condition exists on systems that lack the
+fexecve(2)
+system call when the directory in which the command is located
+is writable by the user.
+See the description of the
+\fIfdexec\fR
+setting for more information on how
+\fBsudo\fR
+executes commands that have an associated digest.
+.PP
+Command digests are only supported by version 1.8.7 or higher.
+.SS "Defaults"
+Certain configuration options may be changed from their default
+values at run-time via one or more
+\fRDefault_Entry\fR
+lines.
+These may affect all users on any host, all users on a specific host, a
+specific user, a specific command, or commands being run as a specific user.
+Note that per-command entries may not include command line arguments.
+If you need to specify arguments, define a
+\fRCmnd_Alias\fR
+and reference
+that instead.
+.nf
+.sp
+.RS 0n
+Default_Type ::= 'Defaults' |
+ 'Defaults' '@' Host_List |
+ 'Defaults' ':' User_List |
+ 'Defaults' '!' Cmnd_List |
+ 'Defaults' '>' Runas_List
+
+Default_Entry ::= Default_Type Parameter_List
+
+Parameter_List ::= Parameter |
+ Parameter ',' Parameter_List
+
+Parameter ::= Parameter '=' Value |
+ Parameter '+=' Value |
+ Parameter '-=' Value |
+ '!'* Parameter
+.RE
+.fi
+.PP
+Parameters may be
+\fBflags\fR,
+\fBinteger\fR
+values,
+\fBstrings\fR,
+or
+\fBlists\fR.
+Flags are implicitly boolean and can be turned off via the
+\(oq\&!\(cq
+operator.
+Some integer, string and list parameters may also be
+used in a boolean context to disable them.
+Values may be enclosed
+in double quotes
+(\&"")
+when they contain multiple words.
+Special characters may be escaped with a backslash
+(\(oq\e\(cq).
+.PP
+Lists have two additional assignment operators,
+\fR+=\fR
+and
+\fR-=\fR.
+These operators are used to add to and delete from a list respectively.
+It is not an error to use the
+\fR-=\fR
+operator to remove an element
+that does not exist in a list.
+.PP
+Defaults entries are parsed in the following order: generic, host,
+user and runas Defaults first, then command defaults.
+If there are multiple Defaults settings of the same type, the last
+matching setting is used.
+The following Defaults settings are parsed before all others since
+they may affect subsequent entries:
+\fIfqdn\fR,
+\fIgroup_plugin\fR,
+\fIrunas_default\fR,
+\fIsudoers_locale\fR.
+.PP
+See
+\fISUDOERS OPTIONS\fR
+for a list of supported Defaults parameters.
+.SS "User specification"
+.nf
+.RS 0n
+User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e
+ (':' Host_List '=' Cmnd_Spec_List)*
+
+Cmnd_Spec_List ::= Cmnd_Spec |
+ Cmnd_Spec ',' Cmnd_Spec_List
+
+Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd
+
+Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
+
+.ie \n(SL \{\
+.ie \n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec)
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec)
+.\}
+.el \{\
+.ie \n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec)
+.el Option_Spec ::= (Date_Spec | Timeout_Spec)
+.\}
+
+.if \n(SL \{\
+SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
+
+.\}
+.if \n(PS \{\
+Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
+
+.\}
+Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
+
+Timeout_Spec ::= 'TIMEOUT=timeout'
+
+Chdir_Spec ::= 'CWD=directory'
+
+Chroot_Spec ::= 'CHROOT=directory'
+
+Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
+ 'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
+ 'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
+ 'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')
+.RE
+.fi
+.PP
+A
+\fBuser specification\fR
+determines which commands a user may run
+(and as what user) on specified hosts.
+By default, commands are
+run as
+\fBroot\fR,
+but this can be changed on a per-command basis.
+.PP
+The basic structure of a user specification is
+\(lqwho where = (as_whom) what\(rq.
+Let's break that down into its constituent parts:
+.SS "Runas_Spec"
+A
+\fRRunas_Spec\fR
+determines the user and/or the group that a command
+may be run as.
+A fully-specified
+\fRRunas_Spec\fR
+consists of two
+\fRRunas_List\fRs
+(as defined above) separated by a colon
+(\(oq:\&\(cq)
+and enclosed in a set of parentheses.
+The first
+\fRRunas_List\fR
+indicates which users the command may be run as via the
+\fB\-u\fR
+option.
+The second defines a list of groups that can be specified via the
+\fB\-g\fR
+option in addition to any of the target user's groups.
+If both
+\fRRunas_List\fRs
+are specified, the command may be run with any combination of users
+and groups listed in their respective
+\fRRunas_List\fRs.
+If only the first is specified, the command may be run as any user
+in the list but no
+\fB\-g\fR
+option
+may be specified.
+If the first
+\fRRunas_List\fR
+is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the
+\fRRunas_List\fR.
+If both
+\fRRunas_List\fRs
+are empty, the command may only be run as the invoking user.
+If no
+\fRRunas_Spec\fR
+is specified the command may be run as
+\fBroot\fR
+and
+no group may be specified.
+.PP
+A
+\fRRunas_Spec\fR
+sets the default for the commands that follow it.
+What this means is that for the entry:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
+.RE
+.fi
+.PP
+The user
+\fBdgb\fR
+may run
+\fI/bin/ls\fR,
+\fI/bin/kill\fR,
+and
+\fI/usr/bin/lprm\fR
+on the host
+boulder\(embut
+only as
+\fBoperator\fR.
+E.g.,
+.nf
+.sp
+.RS 0n
+$ sudo -u operator /bin/ls
+.RE
+.fi
+.PP
+It is also possible to override a
+\fRRunas_Spec\fR
+later on in an entry.
+If we modify the entry like so:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+.RE
+.fi
+.PP
+Then user
+\fBdgb\fR
+is now allowed to run
+\fI/bin/ls\fR
+as
+\fBoperator\fR,
+but
+\fI/bin/kill\fR
+and
+\fI/usr/bin/lprm\fR
+as
+\fBroot\fR.
+.PP
+We can extend this to allow
+\fBdgb\fR
+to run
+\fR/bin/ls\fR
+with either
+the user or group set to
+\fBoperator\fR:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill,\e
+ /usr/bin/lprm
+.RE
+.fi
+.PP
+Note that while the group portion of the
+\fRRunas_Spec\fR
+permits the
+user to run as command with that group, it does not force the user
+to do so.
+If no group is specified on the command line, the command
+will run with the group listed in the target user's password database
+entry.
+The following would all be permitted by the sudoers entry above:
+.nf
+.sp
+.RS 0n
+$ sudo -u operator /bin/ls
+$ sudo -u operator -g operator /bin/ls
+$ sudo -g operator /bin/ls
+.RE
+.fi
+.PP
+In the following example, user
+\fBtcm\fR
+may run commands that access
+a modem device file with the dialer group.
+.nf
+.sp
+.RS 0n
+tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu,\e
+ /usr/local/bin/minicom
+.RE
+.fi
+.PP
+Note that in this example only the group will be set, the command
+still runs as user
+\fBtcm\fR.
+E.g.\&
+.nf
+.sp
+.RS 0n
+$ sudo -g dialer /usr/bin/cu
+.RE
+.fi
+.PP
+Multiple users and groups may be present in a
+\fRRunas_Spec\fR,
+in which case the user may select any combination of users and groups via the
+\fB\-u\fR
+and
+\fB\-g\fR
+options.
+In this example:
+.nf
+.sp
+.RS 0n
+alan ALL = (root, bin : operator, system) ALL
+.RE
+.fi
+.PP
+user
+\fBalan\fR
+may run any command as either user root or bin,
+optionally setting the group to operator or system.
+.SS "Option_Spec"
+A
+\fRCmnd\fR
+may have zero or more options associated with it.
+Options may consist of
+.if \n(SL \{\
+SELinux roles and/or types,
+.\}
+.if \n(PS \{\
+Solaris privileges sets,
+.\}
+start and/or end dates and command timeouts.
+Once an option is set for a
+\fRCmnd\fR,
+subsequent
+\fRCmnd\fRs
+in the
+\fRCmnd_Spec_List\fR,
+inherit that option unless it is overridden by another option.
+Note that the option names are reserved words in
+\fIsudoers\fR.
+This means that none of the valid option names (see below) can be used
+when declaring an alias.
+.if \n(SL \{\
+.SS "SELinux_Spec"
+On systems with SELinux support,
+\fIsudoers\fR
+file entries may optionally have an SELinux role and/or type associated
+with a command.
+If a role or
+type is specified with the command it will override any default values
+specified in
+\fIsudoers\fR.
+A role or type specified on the command line,
+however, will supersede the values in
+\fIsudoers\fR.
+.\}
+.if \n(PS \{\
+.SS "Solaris_Priv_Spec"
+On Solaris systems,
+\fIsudoers\fR
+file entries may optionally specify Solaris privilege set and/or limit
+privilege set associated with a command.
+If privileges or limit privileges are specified with the command
+it will override any default values specified in
+\fIsudoers\fR.
+.PP
+A privilege set is a comma-separated list of privilege names.
+The
+ppriv(1)
+command can be used to list all privileges known to the system.
+For example:
+.nf
+.sp
+.RS 0n
+$ ppriv -l
+.RE
+.fi
+.PP
+In addition, there are several
+\(lqspecial\(rq
+privilege strings:
+.TP 10n
+none
+the empty set
+.TP 10n
+all
+the set of all privileges
+.TP 10n
+zone
+the set of all privileges available in the current zone
+.TP 10n
+basic
+the default set of privileges normal users are granted at login time
+.PP
+Privileges can be excluded from a set by prefixing the privilege
+name with either an
+\(oq\&!\(cq
+or
+\(oq\-\(cq
+character.
+.\}
+.SS "Date_Spec"
+\fBsudoers\fR
+rules can be specified with a start and end date via the
+\fRNOTBEFORE\fR
+and
+\fRNOTAFTER\fR
+settings.
+The time stamp must be specified in
+\fIGeneralized Time\fR
+as defined by RFC 4517.
+The format is effectively
+\fRyyyymmddHHMMSSZ\fR
+where the minutes and seconds are optional.
+The
+\(oqZ\(cq
+suffix indicates that the time stamp is in Coordinated Universal Time (UTC).
+It is also possible to specify a timezone offset from UTC in hours
+and minutes instead of a
+\(oqZ\(cq.
+For example,
+\(oq-0500\(cq
+would correspond to Eastern Standard time in the US.
+As an extension, if no
+\(oqZ\(cq
+or timezone offset is specified, local time will be used.
+.PP
+The following are all valid time stamps:
+.nf
+.sp
+.RS 4n
+20170214083000Z
+2017021408Z
+20160315220000-0500
+20151201235900
+.RE
+.fi
+.SS "Timeout_Spec"
+A command may have a timeout associated with it.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The timeout may be specified in combinations of days, hours,
+minutes and seconds with a single-letter case-insensitive suffix
+that indicates the unit of time.
+For example, a timeout of 7 days, 8 hours, 30 minutes and
+10 seconds would be written as
+\fR7d8h30m10s\fR.
+If a number is specified without a unit, seconds are assumed.
+Any of the days, minutes, hours or seconds may be omitted.
+The order must be from largest to smallest unit and a unit
+may not be specified more than once.
+.PP
+The following are all
+\fIvalid\fR
+timeout values:
+\fR7d8h30m10s\fR,
+\fR14d\fR,
+\fR8h30m\fR,
+\fR600s\fR,
+\fR3600\fR.
+The following are
+\fIinvalid\fR
+timeout values:
+\fR12m2w1d\fR,
+\fR30s10m4h\fR,
+\fR1d2d3h\fR.
+.PP
+This setting is only supported by version 1.8.20 or higher.
+.SS "Chdir_Spec"
+The working directory that the command will be run in can be specified
+using the
+\fRCWD\fR
+setting.
+The
+\fIdirectory\fR
+must be a fully-qualified path name beginning with a
+\(oq/\(cq
+or
+\(oq~\(cq
+character, or the special value
+\(lq*\(rq.
+A value of
+\(lq*\(rq
+indicates that the user may specify the working directory by running
+\fBsudo\fR
+with the
+\fB\-D\fR
+option.
+By default, commands are run from the invoking user's current working
+directory, unless the
+\fB\-i\fR
+option is given.
+Path names of the form
+\fR~user/path/name\fR
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.PP
+This setting is only supported by version 1.9.3 or higher.
+.SS "Chroot_Spec"
+The root directory that the command will be run in can be specified
+using the
+\fRCHROOT\fR
+setting.
+The
+\fIdirectory\fR
+must be a fully-qualified path name beginning with a
+\(oq/\(cq
+or
+\(oq~\(cq
+character, or the special value
+\(lq*\(rq.
+A value of
+\(lq*\(rq
+indicates that the user may specify the root directory by running
+\fBsudo\fR
+with the
+\fB\-R\fR
+option.
+This setting can be used to run the command in a
+chroot(2)
+\(lqsandbox\(rq
+similar to the
+chroot(@mansectsu@)
+utility.
+Path names of the form
+\fR~user/path/name\fR
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.PP
+This setting is only supported by version 1.9.3 or higher.
+.SS "Tag_Spec"
+A command may have zero or more tags associated with it.
+The following tag values are supported:
+\fREXEC\fR,
+\fRNOEXEC\fR,
+\fRFOLLOW\fR,
+\fRNOFOLLOW\fR,
+\fRLOG_INPUT\fR,
+\fRNOLOG_INPUT\fR,
+\fRLOG_OUTPUT\fR,
+\fRNOLOG_OUTPUT\fR,
+\fRMAIL\fR,
+\fRNOMAIL\fR,
+\fRPASSWD\fR,
+\fRNOPASSWD\fR,
+\fRSETENV\fR,
+and
+\fRNOSETENV\fR.
+Once a tag is set on a
+\fRCmnd\fR,
+subsequent
+\fRCmnd\fRs
+in the
+\fRCmnd_Spec_List\fR,
+inherit the tag unless it is overridden by the opposite tag (in other words,
+\fRPASSWD\fR
+overrides
+\fRNOPASSWD\fR
+and
+\fRNOEXEC\fR
+overrides
+\fREXEC\fR).
+.TP 2n
+\fIEXEC\fR and \fINOEXEC\fR
+.sp
+If
+\fBsudo\fR
+has been compiled with
+\fInoexec\fR
+support and the underlying operating system supports it, the
+\fRNOEXEC\fR
+tag can be used to prevent a dynamically-linked executable from
+running further commands itself.
+.sp
+In the following example, user
+\fBaaron\fR
+may run
+\fI/usr/bin/more\fR
+and
+\fI/usr/bin/vi\fR
+but shell escapes will be disabled.
+.nf
+.sp
+.RS 2n
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.RE
+.fi
+.RS 2n
+.sp
+See the
+\fIPreventing shell escapes\fR
+section below for more details on how
+\fRNOEXEC\fR
+works and whether or not it will work on your system.
+.RE
+.TP 2n
+\fIFOLLOW\fR and \fINOFOLLOW\fR
+Starting with version 1.8.15,
+\fBsudoedit\fR
+will not open a file that is a symbolic link unless the
+\fIsudoedit_follow\fR
+flag is enabled.
+The
+\fIFOLLOW\fR
+and
+\fINOFOLLOW\fR
+tags override the value of
+\fIsudoedit_follow\fR
+and can be used to permit (or deny) the editing of symbolic links
+on a per-command basis.
+These tags are only effective for the
+\fIsudoedit\fR
+command and are ignored for all other commands.
+.TP 2n
+\fILOG_INPUT\fR and \fINOLOG_INPUT\fR
+.sp
+These tags override the value of the
+\fIlog_input\fR
+flag on a per-command basis.
+For more information, see the description of
+\fIlog_input\fR
+in the
+\fISUDOERS OPTIONS\fR
+section below.
+.TP 2n
+\fILOG_OUTPUT\fR and \fINOLOG_OUTPUT\fR
+.sp
+These tags override the value of the
+\fIlog_output\fR
+flag on a per-command basis.
+For more information, see the description of
+\fIlog_output\fR
+in the
+\fISUDOERS OPTIONS\fR
+section below.
+.TP 2n
+\fIMAIL\fR and \fINOMAIL\fR
+.sp
+These tags provide fine-grained control over whether
+mail will be sent when a user runs a command by
+overriding the value of the
+\fImail_all_cmnds\fR
+flag on a per-command basis.
+They have no effect when
+\fBsudo\fR
+is run with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options.
+A
+\fINOMAIL\fR
+tag will also override the
+\fImail_always\fR
+and
+\fImail_no_perms\fR
+options.
+For more information, see the descriptions of
+\fImail_all_cmnds\fR,
+\fImail_always\fR,
+and
+\fImail_no_perms\fR
+in the
+\fISUDOERS OPTIONS\fR
+section below.
+.TP 2n
+\fIPASSWD\fR and \fINOPASSWD\fR
+.sp
+By default,
+\fBsudo\fR
+requires that a user authenticate him or herself
+before running a command.
+This behavior can be modified via the
+\fRNOPASSWD\fR
+tag.
+Like a
+\fRRunas_Spec\fR,
+the
+\fRNOPASSWD\fR
+tag sets
+a default for the commands that follow it in the
+\fRCmnd_Spec_List\fR.
+Conversely, the
+\fRPASSWD\fR
+tag can be used to reverse things.
+For example:
+.nf
+.sp
+.RS 2n
+ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+.RE
+.fi
+.RS 2n
+.sp
+would allow the user
+\fBray\fR
+to run
+\fI/bin/kill\fR,
+\fI/bin/ls\fR,
+and
+\fI/usr/bin/lprm\fR
+as
+\fBroot\fR
+on the machine rushmore without authenticating himself.
+If we only want
+\fBray\fR
+to be able to
+run
+\fI/bin/kill\fR
+without a password the entry would be:
+.nf
+.sp
+.RS 2n
+ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+.RE
+.fi
+.sp
+Note, however, that the
+\fRPASSWD\fR
+tag has no effect on users who are in the group specified by the
+\fIexempt_group\fR
+setting.
+.sp
+By default, if the
+\fRNOPASSWD\fR
+tag is applied to any of a user's entries for the current host,
+the user will be able to run
+\(lq\fRsudo -l\fR\(rq
+without a password.
+Additionally, a user may only run
+\(lq\fRsudo -v\fR\(rq
+without a password if all of the user's entries for the current
+host have the
+\fRNOPASSWD\fR
+tag.
+This behavior may be overridden via the
+\fIverifypw\fR
+and
+\fIlistpw\fR
+options.
+.RE
+.TP 2n
+\fISETENV\fR and \fINOSETENV\fR
+.sp
+These tags override the value of the
+\fIsetenv\fR
+flag on a per-command basis.
+Note that if
+\fRSETENV\fR
+has been set for a command, the user may disable the
+\fIenv_reset\fR
+flag from the command line via the
+\fB\-E\fR
+option.
+Additionally, environment variables set on the command
+line are not subject to the restrictions imposed by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR.
+As such, only trusted users should be allowed to set variables in this manner.
+If the command matched is
+\fBALL\fR,
+the
+\fRSETENV\fR
+tag is implied for that command; this default may be overridden by use of the
+\fRNOSETENV\fR
+tag.
+.SS "Wildcards"
+\fBsudo\fR
+allows shell-style
+\fIwildcards\fR
+(aka meta or glob characters)
+to be used in host names, path names and command line arguments in the
+\fIsudoers\fR
+file.
+Wildcard matching is done via the
+glob(3)
+and
+fnmatch(3)
+functions as specified by
+IEEE Std 1003.1 (\(lqPOSIX.1\(rq).
+.TP 10n
+\fR*\fR
+Matches any set of zero or more characters (including white space).
+.TP 10n
+\fR\&?\fR
+Matches any single character (including white space).
+.TP 10n
+\fR[...]\fR
+Matches any character in the specified range.
+.TP 10n
+\fR[!...]\fR
+Matches any character
+\fInot\fR
+in the specified range.
+.TP 10n
+\fR\ex\fR
+For any character
+\(oqx\(cq,
+evaluates to
+\(oqx\(cq.
+This is used to escape special characters such as:
+\(oq*\(cq,
+\(oq\&?\(cq,
+\(oq[\&\(cq,
+and
+\(oq]\&\(cq.
+.PP
+\fBNote that these are not regular expressions.\fR
+Unlike a regular expression there is no way to match one or more
+characters within a range.
+.PP
+Character classes may be used if your system's
+glob(3)
+and
+fnmatch(3)
+functions support them.
+However, because the
+\(oq:\&\(cq
+character has special meaning in
+\fIsudoers\fR,
+it must be
+escaped.
+For example:
+.nf
+.sp
+.RS 4n
+/bin/ls [[\e:\&alpha\e:\&]]*
+.RE
+.fi
+.PP
+Would match any file name beginning with a letter.
+.PP
+Note that a forward slash
+(\(oq/\(cq)
+will
+\fInot\fR
+be matched by
+wildcards used in the file name portion of the command.
+This is to make a path like:
+.nf
+.sp
+.RS 4n
+/usr/bin/*
+.RE
+.fi
+.PP
+match
+\fI/usr/bin/who\fR
+but not
+\fI/usr/bin/X11/xterm\fR.
+.PP
+When matching the command line arguments, however, a slash
+\fIdoes\fR
+get matched by wildcards since command line arguments may contain
+arbitrary strings and not just path names.
+.PP
+\fBWildcards in command line arguments should be used with care.\fR
+.br
+Command line arguments are matched as a single, concatenated string.
+This mean a wildcard character such as
+\(oq\&?\(cq
+or
+\(oq*\(cq
+will match across word boundaries, which may be unexpected.
+For example, while a sudoers entry like:
+.nf
+.sp
+.RS 4n
+%operator ALL = /bin/cat /var/log/messages*
+.RE
+.fi
+.PP
+will allow command like:
+.nf
+.sp
+.RS 4n
+$ sudo cat /var/log/messages.1
+.RE
+.fi
+.PP
+It will also allow:
+.nf
+.sp
+.RS 4n
+$ sudo cat /var/log/messages /etc/shadow
+.RE
+.fi
+.PP
+which is probably not what was intended.
+In most cases it is better to do command line processing
+outside of the
+\fIsudoers\fR
+file in a scripting language.
+.SS "Exceptions to wildcard rules"
+The following exceptions apply to the above rules:
+.TP 10n
+\fR\&""\fR
+If the empty string
+\fR\&""\fR
+is the only command line argument in the
+\fIsudoers\fR
+file entry it means that command is not allowed to be run with
+\fIany\fR
+arguments.
+.TP 10n
+sudoedit
+Command line arguments to the
+\fIsudoedit\fR
+built-in command should always be path names, so a forward slash
+(\(oq/\(cq)
+will not be matched by a wildcard.
+.SS "Including other files from within sudoers"
+It is possible to include other
+\fIsudoers\fR
+files from within the
+\fIsudoers\fR
+file currently being parsed using the
+\fR@include\fR
+and
+\fR@includedir\fR
+directives.
+For compatibility with sudo versions prior to 1.9.1,
+\fR#include\fR
+and
+\fR#includedir\fR
+are also accepted.
+.PP
+An include file can be used, for example, to keep a site-wide
+\fIsudoers\fR
+file in addition to a local, per-machine file.
+For the sake of this example the site-wide
+\fIsudoers\fR
+file will be
+\fI/etc/sudoers\fR
+and the per-machine one will be
+\fI/etc/sudoers.local\fR.
+To include
+\fI/etc/sudoers.local\fR
+from within
+\fI/etc/sudoers\fR
+one would use the following line in
+\fI/etc/sudoers\fR:
+.nf
+.sp
+.RS 4n
+@include /etc/sudoers.local
+.RE
+.fi
+.PP
+When
+\fBsudo\fR
+reaches this line it will suspend processing of the current file
+(\fI/etc/sudoers\fR)
+and switch to
+\fI/etc/sudoers.local\fR.
+Upon reaching the end of
+\fI/etc/sudoers.local\fR,
+the rest of
+\fI/etc/sudoers\fR
+will be processed.
+Files that are included may themselves include other files.
+A hard limit of 128 nested include files is enforced to prevent include
+file loops.
+.PP
+The path to the include file may contain white space if it is
+escaped with a backslash
+(\(oq\e\(cq).
+Alternately, the entire path may be enclosed in double quotes
+(\&""),
+in which case no escaping is necessary.
+To include a literal backslash in the path,
+\(oq\e\e\(cq
+should be used.
+.PP
+If the path to the include file is not fully-qualified (does not
+begin with a
+\(oq/\(cq),
+it must be located in the same directory as the sudoers file it was
+included from.
+For example, if
+\fI/etc/sudoers\fR
+contains the line:
+.nf
+.sp
+.RS 4n
+\fR@include sudoers.local\fR
+.RE
+.fi
+.PP
+the file that will be included is
+\fI/etc/sudoers.local\fR.
+.PP
+The file name may also include the
+\fR%h\fR
+escape, signifying the short form of the host name.
+In other words, if the machine's host name is
+\(lqxerxes\(rq,
+then
+.nf
+.sp
+.RS 4n
+@include /etc/sudoers.%h
+.RE
+.fi
+.PP
+will cause
+\fBsudo\fR
+to include the file
+\fI/etc/sudoers.xerxes\fR.
+.PP
+The
+\fR@includedir\fR
+directive can be used to create a
+\fIsudoers.d\fR
+directory that the system package manager can drop
+\fIsudoers\fR
+file rules into as part of package installation.
+For example, given:
+.nf
+.sp
+.RS 4n
+@includedir /etc/sudoers.d
+.RE
+.fi
+.PP
+\fBsudo\fR
+will suspend processing of the current file and read each file in
+\fI/etc/sudoers.d\fR,
+skipping file names that end in
+\(oq~\(cq
+or contain a
+\(oq.\&\(cq
+character to avoid causing problems with package manager or editor
+temporary/backup files.
+Files are parsed in sorted lexical order.
+That is,
+\fI/etc/sudoers.d/01_first\fR
+will be parsed before
+\fI/etc/sudoers.d/10_second\fR.
+Be aware that because the sorting is lexical, not numeric,
+\fI/etc/sudoers.d/1_whoops\fR
+would be loaded
+\fIafter\fR
+\fI/etc/sudoers.d/10_second\fR.
+Using a consistent number of leading zeroes in the file names can be used
+to avoid such problems.
+After parsing the files in the directory, control returns to the
+file that contained the
+\fR@includedir\fR
+directive.
+.PP
+Note that unlike files included via
+\fR@include\fR,
+\fBvisudo\fR
+will not edit the files in a
+\fR@includedir\fR
+directory unless one of them contains a syntax error.
+It is still possible to run
+\fBvisudo\fR
+with the
+\fB\-f\fR
+flag to edit the files directly, but this will not catch the
+redefinition of an
+\fIalias\fR
+that is also present in a different file.
+.SS "Other special characters and reserved words"
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment (unless it is part of a #include
+directive or unless it occurs in the context of a user name and is
+followed by one or more digits, in which case it is treated as a
+user-ID).
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.PP
+The reserved word
+\fBALL\fR
+is a built-in
+\fIalias\fR
+that always causes a match to succeed.
+It can be used wherever one might otherwise use a
+\fRCmnd_Alias\fR,
+\fRUser_Alias\fR,
+\fRRunas_Alias\fR,
+or
+\fRHost_Alias\fR.
+Attempting to define an
+\fIalias\fR
+named
+\fBALL\fR
+will result in a syntax error.
+Please note that using
+\fBALL\fR
+can be dangerous since in a command context, it allows the user to run
+\fIany\fR
+command on the system.
+.PP
+The following option names permitted in an
+\fROption_Spec\fR
+are also considered reserved words:
+\fRCHROOT\fR,
+.if \n(PS \{\
+\fRPRIVS\fR,
+.\}
+.if \n(PS \{\
+\fRLIMITPRIVS\fR,
+.\}
+.if \n(SL \{\
+\fRROLE\fR,
+.\}
+.if \n(SL \{\
+\fRTYPE\fR,
+.\}
+\fRTIMEOUT\fR,
+\fRCWD\fR,
+\fRNOTBEFORE\fR
+and
+\fRNOTAFTER\fR.
+Attempting to define an
+\fIalias\fR
+with the same name as one of the options will result in a syntax error.
+.PP
+An exclamation point
+(\(oq\&!\(cq)
+can be used as a logical
+\fInot\fR
+operator in a list or
+\fIalias\fR
+as well as in front of a
+\fRCmnd\fR.
+This allows one to exclude certain values.
+For the
+\(oq\&!\(cq
+operator to be effective, there must be something for it to exclude.
+For example, to match all users except for root one would use:
+.nf
+.sp
+.RS 4n
+ALL,!root
+.RE
+.fi
+.PP
+If the
+\fBALL\fR,
+is omitted, as in:
+.nf
+.sp
+.RS 4n
+!root
+.RE
+.fi
+.PP
+it would explicitly deny root but not match any other users.
+This is different from a true
+\(lqnegation\(rq
+operator.
+.PP
+Note, however, that using a
+\(oq\&!\(cq
+in conjunction with the built-in
+\fBALL\fR
+alias to allow a user to run
+\(lqall but a few\(rq
+commands rarely works as intended (see
+\fISECURITY NOTES\fR
+below).
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+.PP
+White space between elements in a list as well as special syntactic
+characters in a
+\fIUser Specification\fR
+(\(oq=\&\(cq,
+\(oq:\&\(cq,
+\(oq(\&\(cq,
+\(oq)\&\(cq)
+is optional.
+.PP
+The following characters must be escaped with a backslash
+(\(oq\e\(cq)
+when used as part of a word (e.g., a user name or host name):
+\(oq\&!\(cq,
+\(oq=\&\(cq,
+\(oq:\&\(cq,
+\(oq,\&\(cq,
+\(oq(\&\(cq,
+\(oq)\&\(cq,
+\(oq\e\(cq.
+.SH "SUDOERS OPTIONS"
+\fBsudo\fR's
+behavior can be modified by
+\fRDefault_Entry\fR
+lines, as explained earlier.
+A list of all supported Defaults parameters, grouped by type, are listed below.
+.PP
+\fBBoolean Flags\fR:
+.TP 18n
+always_query_group_plugin
+If a
+\fIgroup_plugin\fR
+is configured, use it to resolve groups of the form %group as long
+as there is not also a system group of the same name.
+Normally, only groups of the form %:group are passed to the
+\fIgroup_plugin\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+always_set_home
+If enabled,
+\fBsudo\fR
+will set the
+\fRHOME\fR
+environment variable to the home directory of the target user
+(which is the root user unless the
+\fB\-u\fR
+option is used).
+This flag is largely obsolete and has no effect unless the
+\fIenv_reset\fR
+flag has been disabled or
+\fRHOME\fR
+is present in the
+\fIenv_keep\fR
+list, both of which are strongly discouraged.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+authenticate
+If set, users must authenticate themselves via a password (or other
+means of authentication) before they may run commands.
+This default may be overridden via the
+\fRPASSWD\fR
+and
+\fRNOPASSWD\fR
+tags.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+case_insensitive_group
+If enabled, group names in
+\fIsudoers\fR
+will be matched in a case insensitive manner.
+This may be necessary when users are stored in LDAP or AD.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+case_insensitive_user
+If enabled, user names in
+\fIsudoers\fR
+will be matched in a case insensitive manner.
+This may be necessary when groups are stored in LDAP or AD.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+closefrom_override
+If set, the user may use the
+\fB\-C\fR
+option which overrides the default starting point at which
+\fBsudo\fR
+begins closing open file descriptors.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+compress_io
+If set, and
+\fBsudo\fR
+is configured to log a command's input or output,
+the I/O logs will be compressed using
+\fBzlib\fR.
+This flag is
+\fIon\fR
+by default when
+\fBsudo\fR
+is compiled with
+\fBzlib\fR
+support.
+.TP 18n
+exec_background
+By default,
+\fBsudo\fR
+runs a command as the foreground process as long as
+\fBsudo\fR
+itself is running in the foreground.
+When the
+\fIexec_background\fR
+flag is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+\fIuse_pty\fR
+flag), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+\fRSIGTTIN\fR
+signal (or
+\fRSIGTTOU\fR
+in the case of terminal settings).
+If this happens when
+\fBsudo\fR
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+\fBsudo\fR
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+\fIsudo\fR
+behavior or when the command is not being run in a pseudo-terminal.
+.sp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+\fBtcgetattr\fR()
+and
+\fBtcsetattr\fR()
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+\fRSIGTTIN\fR
+or
+\fRSIGTTOU\fR
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+\fRSIGTOP\fR)
+will not be automatically foregrounded.
+Some versions of the linux
+su(1)
+command behave this way.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+It has no effect unless I/O logging is enabled or the
+\fIuse_pty\fR
+flag is enabled.
+.TP 18n
+env_editor
+If set,
+\fBvisudo\fR
+will use the value of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables before falling back on the default editor list.
+Note that
+\fBvisudo\fR
+is typically run as root so this flag may allow a user with
+\fBvisudo\fR
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+\(lqsafe\(rq
+editors int the
+\fIeditor\fR
+variable.
+\fBvisudo\fR
+will then only use
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+if they match a value specified in
+\fIeditor\fR.
+If the
+\fIenv_reset\fR
+flag is enabled, the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+and/or
+\fREDITOR\fR
+environment variables must be present in the
+\fIenv_keep\fR
+list for the
+\fIenv_editor\fR
+flag to function when
+\fBvisudo\fR
+is invoked via
+\fBsudo\fR.
+This flag is
+\fI@env_editor@\fR
+by default.
+.TP 18n
+env_reset
+If set,
+\fBsudo\fR
+will run the command in a minimal environment containing the
+\fRTERM\fR,
+\fRPATH\fR,
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRLOGNAME\fR,
+\fRUSER\fR
+and
+\fRSUDO_*\fR
+variables.
+Any variables in the caller's environment or in the file specified
+by the
+\fIrestricted_env_file\fR
+setting that match the
+\fRenv_keep\fR
+and
+\fRenv_check\fR
+lists are then added, followed by any variables present in the file
+specified by the
+\fIenv_file\fR
+setting (if any).
+The contents of the
+\fRenv_keep\fR
+and
+\fRenv_check\fR
+lists, as modified by global Defaults parameters in
+\fIsudoers\fR,
+are displayed when
+\fBsudo\fR
+is run by root with the
+\fB\-V\fR
+option.
+If the
+\fIsecure_path\fR
+setting is enabled, its value will be used for the
+\fRPATH\fR
+environment variable.
+This flag is
+\fI@env_reset@\fR
+by default.
+.TP 18n
+fast_glob
+Normally,
+\fBsudo\fR
+uses the
+glob(3)
+function to do shell-style globbing when matching path names.
+However, since it accesses the file system,
+glob(3)
+can take a long time to complete for some patterns, especially
+when the pattern references a network file system that is mounted
+on demand (auto mounted).
+The
+\fIfast_glob\fR
+flag causes
+\fBsudo\fR
+to use the
+fnmatch(3)
+function, which does not access the file system to do its matching.
+The disadvantage of
+\fIfast_glob\fR
+is that it is unable to match relative path names such as
+\fI./ls\fR
+or
+\fI../bin/ls\fR.
+This has security implications when path names that include globbing
+characters are used with the negation operator,
+\(oq!\&\(cq,
+as such rules can be trivially bypassed.
+As such, this flag should not be used when the
+\fIsudoers\fR
+file contains rules that contain negated path names which include globbing
+characters.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+fqdn
+Set this flag if you want to put fully qualified host names in the
+\fIsudoers\fR
+file when the local host name (as returned by the
+\fRhostname\fR
+command) does not contain the domain name.
+In other words, instead of myhost you would use myhost.mydomain.edu.
+You may still use the short form if you wish (and even mix the two).
+This flag is only effective when the
+\(lqcanonical\(rq
+host name, as returned by the
+\fBgetaddrinfo\fR()
+or
+\fBgethostbyname\fR()
+function, is a fully-qualified domain name.
+This is usually the case when the system is configured to use DNS
+for host name resolution.
+.sp
+If the system is configured to use the
+\fI/etc/hosts\fR
+file in preference to DNS, the
+\(lqcanonical\(rq
+host name may not be fully-qualified.
+The order that sources are queried for host name resolution
+is usually specified in the
+\fI@nsswitch_conf@\fR,
+\fI@netsvc_conf@\fR,
+\fI/etc/host.conf\fR,
+or, in some cases,
+\fI/etc/resolv.conf\fR
+file.
+In the
+\fI/etc/hosts\fR
+file, the first host name of the entry is considered to be the
+\(lqcanonical\(rq
+name; subsequent names are aliases that are not used by
+\fBsudoers\fR.
+For example, the following hosts file line for the machine
+\(lqxyzzy\(rq
+has the fully-qualified domain name as the
+\(lqcanonical\(rq
+host name, and the short version as an alias.
+.sp
+.RS 24n
+192.168.1.1 xyzzy.sudo.ws xyzzy
+.RE
+.RS 18n
+.sp
+If the machine's hosts file entry is not formatted properly, the
+\fIfqdn\fR
+flag will not be effective if it is queried before DNS.
+.sp
+Beware that when using DNS for host name resolution, turning on
+\fIfqdn\fR
+requires
+\fBsudoers\fR
+to make DNS lookups which renders
+\fBsudo\fR
+unusable if DNS stops working (for example if the machine is disconnected
+from the network).
+Also note that just like with the hosts file, you must use the
+\(lqcanonical\(rq
+name as DNS knows it.
+That is, you may not use a host alias
+(\fRCNAME\fR
+entry)
+due to performance issues and the fact that there is no way to get all
+aliases from DNS.
+.sp
+This flag is
+\fI@fqdn@\fR
+by default.
+.RE
+.TP 18n
+ignore_audit_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the audit log.
+If enabled, an audit log write failure is not treated as a fatal error.
+If disabled, a command may only be run after the audit event is successfully
+written.
+This flag is only effective on systems for which
+\fBsudoers\fR
+supports audit logging, including
+FreeBSD,
+Linux, macOS and Solaris.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+ignore_dot
+If set,
+\fBsudo\fR
+will ignore "." or "" (both denoting current directory) in the
+\fRPATH\fR
+environment variable; the
+\fRPATH\fR
+itself is not modified.
+This flag is
+\fI@ignore_dot@\fR
+by default.
+.TP 18n
+ignore_iolog_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the I/O log (local or remote).
+If enabled, an I/O log write failure is not treated as a fatal error.
+If disabled, the command will be terminated if the I/O log cannot be written to.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+ignore_logfile_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the log file.
+If enabled, a log file write failure is not treated as a fatal error.
+If disabled, a command may only be run after the log file entry is successfully
+written.
+This flag only has an effect when
+\fBsudoers\fR
+is configured to use file-based logging via the
+\fIlogfile\fR
+setting.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+ignore_local_sudoers
+If set via LDAP, parsing of
+\fI@sysconfdir@/sudoers\fR
+will be skipped.
+This is intended for Enterprises that wish to prevent the usage of local
+sudoers files so that only LDAP is used.
+This thwarts the efforts of rogue operators who would attempt to add roles to
+\fI@sysconfdir@/sudoers\fR.
+When this flag is enabled,
+\fI@sysconfdir@/sudoers\fR
+does not even need to exist.
+Since this flag tells
+\fBsudo\fR
+how to behave when no specific LDAP entries have been matched, this
+sudoOption is only meaningful for the
+\fRcn=defaults\fR
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+ignore_unknown_defaults
+If set,
+\fBsudo\fR
+will not produce a warning if it encounters an unknown Defaults entry
+in the
+\fIsudoers\fR
+file or an unknown sudoOption in LDAP.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+insults
+If set,
+\fBsudo\fR
+will insult users when they enter an incorrect password.
+This flag is
+\fI@insults@\fR
+by default.
+.TP 18n
+log_allowed
+If set,
+\fBsudoers\fR
+will log commands allowed by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.29 or higher.
+.TP 18n
+log_denied
+If set,
+\fBsudoers\fR
+will log commands denied by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.29 or higher.
+.TP 18n
+log_host
+If set, the host name will be included in log entries written to
+the file configured by the
+\fIlogfile\fR
+setting.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_input
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal and log all user input.
+If the standard input is not connected to the user's tty, due to
+I/O redirection or because the command is part of a pipeline, that
+input is also captured and stored in a separate log file.
+Anything sent to the standard input will be consumed, regardless of
+whether or not the command run via
+\fBsudo\fR
+is actually reading the standard input.
+This may have unexpected results when using
+\fBsudo\fR
+in a shell script that expects to process the standard input.
+For more information about I/O logging, see the
+\fII/O LOG FILES\fR
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_output
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal and log all output that is sent
+to the screen, similar to the
+script(1)
+command.
+For more information about I/O logging, see the
+\fII/O LOG FILES\fR
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_server_keepalive
+If set,
+\fBsudo\fR
+will enable the TCP keepalive socket option on the connection to the log server.
+This enables the periodic transmission of keepalive messages to the server.
+If the server does not respond to a message, the connection will
+be closed and the running command will be terminated unless the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_verify
+.br
+If set, the server certificate received during the TLS handshake
+must be valid and it must contain either the server name (from
+\fIlog_servers\fR)
+or its IP address.
+If either of these conditions is not met, the TLS handshake will fail.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_year
+If set, the four-digit year will be logged in the (non-syslog)
+\fBsudo\fR
+log file.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+long_otp_prompt
+When validating with a One Time Password (OTP) scheme such as
+\fBS/Key\fR
+or
+\fBOPIE\fR,
+a two-line prompt is used to make it easier
+to cut and paste the challenge to a local window.
+It's not as pretty as the default but some people find it more convenient.
+This flag is
+\fI@long_otp_prompt@\fR
+by default.
+.TP 18n
+mail_all_cmnds
+Send mail to the
+\fImailto\fR
+user every time a user attempts to run a command via
+\fBsudo\fR
+(this includes
+\fBsudoedit\fR).
+No mail will be sent if the user runs
+\fBsudo\fR
+with the
+\fB\-l\fR
+or
+\fB\-v\fR
+option unless there is an authentication error and the
+\fImail_badpass\fR
+flag is also set.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_always
+Send mail to the
+\fImailto\fR
+user every time a user runs
+\fBsudo\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_badpass
+Send mail to the
+\fImailto\fR
+user if the user running
+\fBsudo\fR
+does not enter the correct password.
+If the command the user is attempting to run is not permitted by
+\fBsudoers\fR
+and one of the
+\fImail_all_cmnds\fR,
+\fImail_always\fR,
+\fImail_no_host\fR,
+\fImail_no_perms\fR
+or
+\fImail_no_user\fR
+flags are set, this flag will have no effect.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_no_host
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user exists in the
+\fIsudoers\fR
+file, but is not allowed to run commands on the current host.
+This flag is
+\fI@mail_no_host@\fR
+by default.
+.TP 18n
+mail_no_perms
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user is allowed to use
+\fBsudo\fR
+but the command they are trying is not listed in their
+\fIsudoers\fR
+file entry or is explicitly denied.
+This flag is
+\fI@mail_no_perms@\fR
+by default.
+.TP 18n
+mail_no_user
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user is not in the
+\fIsudoers\fR
+file.
+This flag is
+\fI@mail_no_user@\fR
+by default.
+.TP 18n
+match_group_by_gid
+By default,
+\fBsudoers\fR
+will look up each group the user is a member of by group-ID to
+determine the group name (this is only done once).
+The resulting list of the user's group names is used when matching
+groups listed in the
+\fIsudoers\fR
+file.
+This works well on systems where the number of groups listed in the
+\fIsudoers\fR
+file is larger than the number of groups a typical user belongs to.
+On systems where group lookups are slow, where users may belong
+to a large number of groups, and where the number of groups listed
+in the
+\fIsudoers\fR
+file is relatively small, it may be prohibitively expensive and
+running commands via
+\fBsudo\fR
+may take longer than normal.
+On such systems it may be faster to use the
+\fImatch_group_by_gid\fR
+flag to avoid resolving the user's group-IDs to group names.
+In this case,
+\fBsudoers\fR
+must look up any group name listed in the
+\fIsudoers\fR
+file and use the group-ID instead of the group name when determining
+whether the user is a member of the group.
+.sp
+Note that if
+\fImatch_group_by_gid\fR
+is enabled, group database lookups performed by
+\fBsudoers\fR
+will be keyed by group name as opposed to group-ID.
+On systems where there are multiple sources for the group database,
+it is possible to have conflicting group names or group-IDs in the local
+\fI/etc/group\fR
+file and the remote group database.
+On such systems, enabling or disabling
+\fImatch_group_by_gid\fR
+can be used to choose whether group database queries are performed
+by name (enabled) or ID (disabled), which may aid in working around
+group entry conflicts.
+.sp
+The
+\fImatch_group_by_gid\fR
+flag has no effect when
+\fIsudoers\fR
+data is stored in LDAP.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.18 or higher.
+.TP 18n
+netgroup_tuple
+If set, netgroup lookups will be performed using the full netgroup
+tuple: host name, user name and domain (if one is set).
+Historically,
+\fBsudo\fR
+only matched the user name and domain for netgroups used in a
+\fRUser_List\fR
+and only matched the host name and domain for netgroups used in a
+\fRHost_List\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+noexec
+If set, all commands run via
+\fBsudo\fR
+will behave as if the
+\fRNOEXEC\fR
+tag has been set, unless overridden by an
+\fREXEC\fR
+tag.
+See the description of
+\fIEXEC and NOEXEC\fR
+above as well as the
+\fIPreventing shell escapes\fR
+section at the end of this manual.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+pam_acct_mgmt
+On systems that use PAM for authentication,
+\fBsudo\fR
+will perform PAM account validation for the invoking user by default.
+The actual checks performed depend on which PAM modules are configured.
+If enabled, account validation will be performed regardless of whether
+or not a password is required.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.28 or higher.
+.TP 18n
+pam_rhost
+On systems that use PAM for authentication,
+\fBsudo\fR
+will set the PAM remote host value to the name of the local host
+when the
+\fIpam_rhost\fR
+flag is enabled.
+On Linux systems, enabling
+\fIpam_rhost\fR
+may result in DNS lookups of the local host name when PAM is initialized.
+On Solaris versions prior to Solaris 8,
+\fIpam_rhost\fR
+must be enabled if
+\fIpam_ruser\fR
+is also enabled to avoid a crash in the Solaris PAM implementation.
+.sp
+This flag is
+\fIoff\fR
+by default on systems other than Solaris.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+pam_ruser
+On systems that use PAM for authentication,
+\fBsudo\fR
+will set the PAM remote user value to the name of the user that invoked sudo
+when the
+\fIpam_ruser\fR
+flag is enabled.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+pam_session
+On systems that use PAM for authentication,
+\fBsudo\fR
+will create a new PAM session for the command to be run in.
+Unless
+\fBsudo\fR
+is given the
+\fB\-i\fR
+or
+\fB\-s\fR
+options, PAM session modules are run with the
+\(lqsilent\(rq
+flag enabled.
+This prevents last login information from being displayed for every
+command on some systems.
+Disabling
+\fIpam_session\fR
+may be needed on older PAM implementations or on operating systems where
+opening a PAM session changes the utmp or wtmp files.
+If PAM session support is disabled, resource limits may not be updated
+for the command being run.
+If
+\fIpam_session\fR,
+\fIpam_setcred\fR,
+and
+\fIuse_pty\fR
+are disabled,
+\fIlog_servers\fR
+has not been set and I/O logging has not been configured,
+\fBsudo\fR
+will execute the command directly instead of running it as a child
+process.
+This flag is
+\fI@pam_session@\fR
+by default.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+.TP 18n
+pam_setcred
+On systems that use PAM for authentication,
+\fBsudo\fR
+will attempt to establish credentials for the target user by default,
+if supported by the underlying authentication system.
+One example of a credential is a Kerberos ticket.
+If
+\fIpam_session\fR,
+\fIpam_setcred\fR,
+and
+\fIuse_pty\fR
+are disabled,
+\fIlog_servers\fR
+has not been set and I/O logging has not been configured,
+\fBsudo\fR
+will execute the command directly instead of running it as a child
+process.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+passprompt_override
+If set, the prompt specified by
+\fIpassprompt\fR
+or the
+\fRSUDO_PROMPT\fR
+environment variable will always be used and will replace the
+prompt provided by a PAM module or other authentication method.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+path_info
+Normally,
+\fBsudo\fR
+will tell the user when a command could not be
+found in their
+\fRPATH\fR
+environment variable.
+Some sites may wish to disable this as it could be used to gather
+information on the location of executables that the normal user does
+not have access to.
+The disadvantage is that if the executable is simply not in the user's
+\fRPATH\fR,
+\fBsudo\fR
+will tell the user that they are not allowed to run it, which can be confusing.
+This flag is
+\fI@path_info@\fR
+by default.
+.TP 18n
+preserve_groups
+By default,
+\fBsudo\fR
+will initialize the group vector to the list of groups the target user is in.
+When
+\fIpreserve_groups\fR
+is set, the user's existing group vector is left unaltered.
+The real and effective group-IDs, however, are still set to match the
+target user.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+pwfeedback
+By default,
+\fBsudo\fR
+reads the password like most other Unix programs,
+by turning off echo until the user hits the return (or enter) key.
+Some users become confused by this as it appears to them that
+\fBsudo\fR
+has hung at this point.
+When
+\fIpwfeedback\fR
+is set,
+\fBsudo\fR
+will provide visual feedback when the user presses a key.
+Note that this does have a security impact as an onlooker may be able to
+determine the length of the password being entered.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+requiretty
+If set,
+\fBsudo\fR
+will only run when the user is logged in to a real tty.
+When this flag is set,
+\fBsudo\fR
+can only be run from a login session and not via other means such as
+cron(@mansectsu@)
+or cgi-bin scripts.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+root_sudo
+If set, root is allowed to run
+\fBsudo\fR
+too.
+Disabling this prevents users from
+\(lqchaining\(rq
+\fBsudo\fR
+commands to get a root shell by doing something like
+\(lq\fRsudo sudo /bin/sh\fR\(rq.
+Note, however, that turning off
+\fIroot_sudo\fR
+will also prevent root from running
+\fBsudoedit\fR.
+Disabling
+\fIroot_sudo\fR
+provides no real additional security; it exists purely for historical reasons.
+This flag is
+\fI@root_sudo@\fR
+by default.
+.TP 18n
+rootpw
+If set,
+\fBsudo\fR
+will prompt for the root password instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+runas_allow_unknown_id
+If enabled, allow matching of runas user and group IDs that are
+not present in the password or group databases.
+In addition to explicitly matching unknown user or group IDs in a
+\fRRunas_List\fR,
+this option also allows the
+\fBALL\fR
+alias to match unknown IDs.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.30 or higher.
+Older versions of
+\fBsudo\fR
+always allowed matching of unknown user and group IDs.
+.TP 18n
+runas_check_shell
+.br
+If enabled,
+\fBsudo\fR
+will only run commands as a user whose shell appears in the
+\fI/etc/shells\fR
+file, even if the invoking user's
+\fRRunas_List\fR
+would otherwise permit it.
+If no
+\fI/etc/shells\fR
+file is present, a system-dependent list of built-in default shells is used.
+On many operating systems, system users such as
+\(lqbin\(rq,
+do not have a valid shell and this flag can be used to prevent
+commands from being run as those users.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.30 or higher.
+.TP 18n
+runaspw
+If set,
+\fBsudo\fR
+will prompt for the password of the user defined by the
+\fIrunas_default\fR
+option (defaults to
+\fR@runas_default@\fR)
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+\fIoff\fR
+by default.
+.if \n(SL \{\
+.TP 18n
+selinux
+If enabled, the user may specify an SELinux role and/or type to use
+when running the command, as permitted by the SELinux policy.
+If SELinux is disabled on the system, this flag has no effect.
+This flag is
+\fIon\fR
+by default.
+.\}
+.TP 18n
+set_home
+If enabled and
+\fBsudo\fR
+is invoked with the
+\fB\-s\fR
+option, the
+\fRHOME\fR
+environment variable will be set to the home directory of the target
+user (which is the root user unless the
+\fB\-u\fR
+option is used).
+This flag is largely obsolete and has no effect unless the
+\fIenv_reset\fR
+flag has been disabled or
+\fRHOME\fR
+is present in the
+\fIenv_keep\fR
+list, both of which are strongly discouraged.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+set_logname
+Normally,
+\fBsudo\fR
+will set the
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+environment variables to the name of the target user (usually root unless the
+\fB\-u\fR
+option is given).
+However, since some programs (including the RCS revision control system) use
+\fRLOGNAME\fR
+to determine the real identity of the user, it may be desirable to
+change this behavior.
+This can be done by negating the set_logname option.
+Note that
+\fIset_logname\fR
+will have no effect
+if the
+\fIenv_reset\fR
+option has not been disabled and the
+\fIenv_keep\fR
+list contains
+\fRLOGNAME\fR
+or
+\fRUSER\fR.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+set_utmp
+When enabled,
+\fBsudo\fR
+will create an entry in the utmp (or utmpx) file when a pseudo-terminal
+is allocated.
+A pseudo-terminal is allocated by
+\fBsudo\fR
+when it is running in a terminal and one or more of the
+\fIlog_input\fR,
+\fIlog_output\fR
+or
+\fIuse_pty\fR
+flags is enabled.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+setenv
+Allow the user to disable the
+\fIenv_reset\fR
+option from the command line via the
+\fB\-E\fR
+option.
+Additionally, environment variables set via the command line are
+not subject to the restrictions imposed by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR.
+As such, only trusted users should be allowed to set variables in this manner.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+shell_noargs
+If set and
+\fBsudo\fR
+is invoked with no arguments it acts as if the
+\fB\-s\fR
+option had been given.
+That is, it runs a shell as root (the shell is determined by the
+\fRSHELL\fR
+environment variable if it is set, falling back on the shell listed
+in the invoking user's /etc/passwd entry if not).
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+stay_setuid
+Normally, when
+\fBsudo\fR
+executes a command the real and effective UIDs are set to the target
+user (root by default).
+This option changes that behavior such that the real UID is left
+as the invoking user's UID.
+In other words, this makes
+\fBsudo\fR
+act as a set-user-ID wrapper.
+This can be useful on systems that disable some potentially
+dangerous functionality when a program is run set-user-ID.
+This option is only effective on systems that support either the
+setreuid(2)
+or
+setresuid(2)
+system call.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+sudoedit_checkdir
+.br
+If set,
+\fBsudoedit\fR
+will check all directory components of the path to be edited for writability
+by the invoking user.
+Symbolic links will not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+\fBsudoedit\fR
+is run by root.
+On some systems, if all directory components of the path to be edited
+are not readable by the target user,
+\fBsudoedit\fR
+will be unable to edit the file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting was first introduced in version 1.8.15 but initially
+suffered from a race condition.
+The check for symbolic links in writable intermediate directories
+was added in version 1.8.16.
+.TP 18n
+sudoedit_follow
+By default,
+\fBsudoedit\fR
+will not follow symbolic links when opening files.
+The
+\fIsudoedit_follow\fR
+option can be enabled to allow
+\fBsudoedit\fR
+to open symbolic links.
+It may be overridden on a per-command basis by the
+\fIFOLLOW\fR
+and
+\fINOFOLLOW\fR
+tags.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.15 or higher.
+.TP 18n
+syslog_pid
+When logging via
+syslog(3),
+include the process ID in the log entry.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.21 or higher.
+.TP 18n
+targetpw
+If set,
+\fBsudo\fR
+will prompt for the password of the user specified
+by the
+\fB\-u\fR
+option (defaults to
+\fRroot\fR)
+instead of the password of the invoking user
+when running a command or editing a file.
+Note that this flag precludes the use of a user-ID not listed in the passwd
+database as an argument to the
+\fB\-u\fR
+option.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+tty_tickets
+If set, users must authenticate on a per-tty basis.
+With this flag enabled,
+\fBsudo\fR
+will use a separate record in the time stamp file for each terminal.
+If disabled, a single record is used for all login sessions.
+.sp
+This option has been superseded by the
+\fItimestamp_type\fR
+option.
+.TP 18n
+umask_override
+If set,
+\fBsudo\fR
+will set the umask as specified in the
+\fIsudoers\fR
+file without modification.
+This makes it possible to specify a umask in the
+\fIsudoers\fR
+file that is more permissive than the user's own umask and matches
+historical behavior.
+If
+\fIumask_override\fR
+is not set,
+\fBsudo\fR
+will set the umask to be the union of the user's umask and what is specified in
+\fIsudoers\fR.
+This flag is
+\fI@umask_override@\fR
+by default.
+.if \n(BA \{\
+.TP 18n
+use_loginclass
+If set,
+\fBsudo\fR
+will apply the defaults specified for the target user's login class
+if one exists.
+Only available if
+\fBsudo\fR
+is configured with the
+\fR--with-logincap\fR
+option.
+This flag is
+\fIoff\fR
+by default.
+.\}
+.TP 18n
+use_netgroups
+If set, netgroups (prefixed with
+\(oq+\(cq),
+may be used in place of a user or host.
+For LDAP-based sudoers, netgroup support requires an expensive
+sub-string match on the server unless the
+\fBNETGROUP_BASE\fR
+directive is present in the
+\fI@ldap_conf@\fR
+file.
+If netgroups are not needed, this option can be disabled to reduce the
+load on the LDAP server.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+use_pty
+If set, and
+\fBsudo\fR
+is running in a terminal, the command will be run in a pseudo-terminal
+(even if no I/O logging is being done).
+If the
+\fBsudo\fR
+process is not attached to a terminal,
+\fIuse_pty\fR
+has no effect.
+.sp
+A malicious program run under
+\fBsudo\fR
+may be capable of injecting commands into the user's
+terminal or running a background process that retains access to the
+user's terminal device even after the main program has finished
+executing.
+By running the command in a separate pseudo-terminal, this attack is
+no longer possible.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+user_command_timeouts
+If set, the user may specify a timeout on the command line.
+If the timeout expires before the command has exited, the
+command will be terminated.
+If a timeout is specified both in the
+\fIsudoers\fR
+file and on the command line, the smaller of the two timeouts will be used.
+See the
+\fRTimeout_Spec\fR
+section for a description of the timeout syntax.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+utmp_runas
+If set,
+\fBsudo\fR
+will store the name of the runas user when updating the utmp (or utmpx) file.
+By default,
+\fBsudo\fR
+stores the name of the invoking user.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+visiblepw
+By default,
+\fBsudo\fR
+will refuse to run if the user must enter a password but it is not
+possible to disable echo on the terminal.
+If the
+\fIvisiblepw\fR
+flag is set,
+\fBsudo\fR
+will prompt for a password even when it would be visible on the screen.
+This makes it possible to run things like
+\(lq\fRssh somehost sudo ls\fR\(rq
+since by default,
+ssh(1)
+does
+not allocate a tty when running a command.
+This flag is
+\fIoff\fR
+by default.
+.PP
+\fBIntegers\fR:
+.TP 18n
+closefrom
+Before it executes a command,
+\fBsudo\fR
+will close all open file descriptors other than standard input,
+standard output and standard error (ie: file descriptors 0-2).
+The
+\fIclosefrom\fR
+option can be used to specify a different file descriptor at which
+to start closing.
+The default is
+\fR3\fR.
+.TP 18n
+command_timeout
+The maximum amount of time a command is allowed to run before
+it is terminated.
+See the
+\fRTimeout_Spec\fR
+section for a description of the timeout syntax.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+log_server_timeout
+The maximum amount of time to wait when connecting to a log server
+or waiting for a server response.
+See the
+\fRTimeout_Spec\fR
+section for a description of the timeout syntax.
+The default value is 30 seconds.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+maxseq
+The maximum sequence number that will be substituted for the
+\(lq\fR%{seq}\fR\(rq
+escape in the I/O log file (see the
+\fIiolog_dir\fR
+description below for more information).
+While the value substituted for
+\(lq\fR%{seq}\fR\(rq
+is in base 36,
+\fImaxseq\fR
+itself should be expressed in decimal.
+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.
+.sp
+Once the local sequence number reaches the value of
+\fImaxseq\fR,
+it will
+\(lqroll over\(rq
+to zero, after which
+\fBsudoers\fR
+will truncate and re-use any existing I/O log path names.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+.TP 18n
+passwd_tries
+The number of tries a user gets to enter his/her password before
+\fBsudo\fR
+logs the failure and exits.
+The default is
+\fR@passwd_tries@\fR.
+.TP 18n
+syslog_maxlen
+On many systems,
+syslog(3)
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+\fBsudoers\fR
+creates log messages up to 980 bytes which corresponds to the
+historic
+BSD
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname and program name.
+To prevent syslog messages from being truncated,
+\fBsudoers\fR
+will split up log messages that are larger than
+\fIsyslog_maxlen\fR
+bytes.
+When a message is split, additional parts will include the string
+\(lq(command continued)\(rq
+after the user name and before the continued command line arguments.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.PP
+\fBIntegers that can be used in a boolean context\fR:
+.TP 18n
+loglinelen
+Number of characters per line for the file log.
+This value is used to decide when to wrap lines for nicer log files.
+This has no effect on the syslog log file, only the file log.
+The default is
+\fR@loglen@\fR
+(use 0 or negate the option to disable word wrap).
+.TP 18n
+passwd_timeout
+Number of minutes before the
+\fBsudo\fR
+password prompt times out, or
+\fR0\fR
+for no timeout.
+The timeout may include a fractional component
+if minute granularity is insufficient, for example
+\fR2.5\fR.
+The
+default is
+\fR@password_timeout@\fR.
+.TP 18n
+timestamp_timeout
+.br
+Number of minutes that can elapse before
+\fBsudo\fR
+will ask for a passwd again.
+The timeout may include a fractional component if
+minute granularity is insufficient, for example
+\fR2.5\fR.
+The default is
+\fR@timeout@\fR.
+Set this to
+\fR0\fR
+to always prompt for a password.
+If set to a value less than
+\fR0\fR
+the user's time stamp will not expire until the system is rebooted.
+This can be used to allow users to create or delete their own time stamps via
+\(lq\fRsudo -v\fR\(rq
+and
+\(lq\fRsudo -k\fR\(rq
+respectively.
+.TP 18n
+umask
+File mode creation mask to use when running the command.
+Negate this option or set it to 0777 to prevent
+\fBsudoers\fR
+from changing the umask.
+Unless the
+\fIumask_override\fR
+flag is set, the actual umask will be the union of the
+user's umask and the value of the
+\fIumask\fR
+setting, which defaults to
+\fR@sudo_umask@\fR.
+This guarantees
+that
+\fBsudo\fR
+never lowers the umask when running a command.
+.sp
+If
+\fIumask\fR
+is explicitly set in
+\fIsudoers\fR,
+it will override any umask setting in PAM or login.conf.
+If
+\fIumask\fR
+is not set in
+\fIsudoers\fR,
+the umask specified by PAM or login.conf will take precedence.
+The umask setting in PAM is not used for
+\fBsudoedit\fR,
+which does not create a new PAM session.
+.PP
+\fBStrings\fR:
+.TP 18n
+authfail_message
+Message that is displayed after a user fails to authenticate.
+The message may include the
+\(oq%d\(cq
+escape which will expand to the number of failed password attempts.
+If set, it overrides the default message,
+\fR%d incorrect password attempt(s)\fR.
+.TP 18n
+badpass_message
+Message that is displayed if a user enters an incorrect password.
+The default is
+\fR@badpass_message@\fR
+unless insults are enabled.
+.TP 18n
+editor
+A colon
+(\(oq:\&\(cq)
+separated list of editors path names used by
+\fBsudoedit\fR
+and
+\fBvisudo\fR.
+For
+\fBsudoedit\fR,
+this list is used to find an editor when none of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables are set to an editor that exists and is executable.
+For
+\fBvisudo\fR,
+it is used as a white list of allowed editors;
+\fBvisudo\fR
+will choose the editor that matches the user's
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variable if possible, or the first editor in the
+list that exists and is executable if not.
+Unless invoked as
+\fBsudoedit\fR,
+\fBsudo\fR
+does not preserve the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables unless they are present in the
+\fIenv_keep\fR
+list or the
+\fIenv_reset\fR
+option is disabled.
+The default is
+\fI@editor@\fR.
+.TP 18n
+iolog_dir
+The top-level directory to use when constructing the path name for
+the input/output log directory.
+Only used if the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+options are enabled or when the
+\fRLOG_INPUT\fR
+or
+\fRLOG_OUTPUT\fR
+tags are present for a command.
+The session sequence number, if any, is stored in the directory.
+The default is
+\fI@iolog_dir@\fR.
+.sp
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 18n
+.PD 0
+.TP 6n
+\fR%{seq}\fR
+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
+expanded to the invoking user's login name
+.TP 6n
+\fR%{group}\fR
+expanded to the name of the invoking user's real group-ID
+.TP 6n
+\fR%{runas_user}\fR
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.TP 6n
+\fR%{runas_group}\fR
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.TP 6n
+\fR%{hostname}\fR
+expanded to the local host name without the domain name
+.TP 6n
+\fR%{command}\fR
+expanded to the base name of the command being run
+.PP
+In addition, any escape sequences supported by the system's
+strftime(3)
+function will be expanded.
+.sp
+To include a literal
+\(oq%\(cq
+character, the string
+\(oq%%\(cq
+should be used.
+.RE
+.TP 18n
+iolog_file
+The path name, relative to
+\fIiolog_dir\fR,
+in which to store input/output logs when the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+options are enabled or when the
+\fRLOG_INPUT\fR
+or
+\fRLOG_OUTPUT\fR
+tags are present for a command.
+Note that
+\fIiolog_file\fR
+may contain directory components.
+The default is
+\(lq\fR%{seq}\fR\(rq.
+.sp
+See the
+\fIiolog_dir\fR
+option above for a list of supported percent
+(\(oq%\(cq)
+escape sequences.
+.sp
+In addition to the escape sequences, path names that end in six or
+more
+\fRX\fRs
+will have the
+\fRX\fRs
+replaced with a unique combination of digits and letters, similar to the
+mktemp(3)
+function.
+.sp
+If the path created by concatenating
+\fIiolog_dir\fR
+and
+\fIiolog_file\fR
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+\fIiolog_file\fR
+ends in six or
+more
+\fRX\fRs.
+.TP 18n
+iolog_flush
+If set,
+\fBsudo\fR
+will flush I/O log data to disk after each write instead of buffering it.
+This makes it possible to view the logs in real-time as the program
+is executing but may significantly reduce the effectiveness of I/O
+log compression.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+iolog_group
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+\fIiolog_group\fR
+is not set,
+the primary group-ID of the user specified by
+\fIiolog_user\fR
+is used.
+If neither
+\fIiolog_group\fR
+nor
+\fIiolog_user\fR
+are set, I/O log files and directories are created with group-ID 0.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+iolog_mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+\fIiolog_mode\fR.
+Defaults to 0600 (read and write by user only).
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+iolog_user
+The user name to look up when setting the user and group-IDs on new
+I/O log files and directories.
+If
+\fIiolog_group\fR
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.sp
+This setting can be useful when the I/O logs are stored on a Network
+File System (NFS) share.
+Having a dedicated user own the I/O log files means that
+\fBsudoers\fR
+does not write to the log files as user-ID 0, which is usually
+not permitted by NFS.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+lecture_status_dir
+The directory in which
+\fBsudo\fR
+stores per-user lecture status files.
+Once a user has received the lecture, a zero-length file is
+created in this directory so that
+\fBsudo\fR
+will not lecture the user again.
+This directory should
+\fInot\fR
+be cleared when the system reboots.
+The default is
+\fI@vardir@/lectured\fR.
+.if \n(PS \{\
+.TP 18n
+limitprivs
+The default Solaris limit privileges to use when constructing a new
+privilege set for a command.
+This bounds all privileges of the executing process.
+The default limit privileges may be overridden on a per-command basis in
+\fIsudoers\fR.
+This option is only available if
+\fBsudoers\fR
+is built on Solaris 10 or higher.
+.\}
+.TP 18n
+log_server_cabundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+This setting has no effect unless
+\fIlog_servers\fR
+is set and the remote log server is secured with TLS.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_peer_cert
+The path to the client's certificate file, in PEM format.
+This setting is required when
+\fIlog_servers\fR
+is set and the remote log server is secured with TLS.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_peer_key
+The path to the client's private key file, in PEM format.
+This setting is required when
+\fIlog_servers\fR
+is set and the remote log server is secured with TLS.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+mailsub
+Subject of the mail sent to the
+\fImailto\fR
+user.
+The escape
+\fR%h\fR
+will expand to the host name of the machine.
+Default is
+\(lq\fR@mailsub@\fR\(rq.
+.TP 18n
+noexec_file
+As of
+\fBsudo\fR
+version 1.8.1 this option is no longer supported.
+The path to the noexec file should now be set in the
+sudo.conf(@mansectform@)
+file.
+.TP 18n
+pam_login_service
+.br
+On systems that use PAM for authentication, this is the service
+name used when the
+\fB\-i\fR
+option is specified.
+The default value is
+\(lq\fR@pam_login_service@\fR\(rq.
+See the description of
+\fIpam_service\fR
+for more information.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+pam_service
+On systems that use PAM for authentication, the service name
+specifies the PAM policy to apply.
+This usually corresponds to an entry in the
+\fIpam.conf\fR
+file or a file in the
+\fI/etc/pam.d\fR
+directory.
+The default value is
+\(lq\fRsudo\fR\(rq.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+passprompt
+The default prompt to use when asking for a password; can be overridden via the
+\fB\-p\fR
+option or the
+\fRSUDO_PROMPT\fR
+environment variable.
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 18n
+.PD 0
+.TP 6n
+\fR%H\fR
+expanded to the local host name including the domain name
+(only if the machine's host name is fully qualified or the
+\fIfqdn\fR
+option is set)
+.PD
+.TP 6n
+\fR%h\fR
+expanded to the local host name without the domain name
+.TP 6n
+\fR%p\fR
+expanded to the user whose password is being asked for (respects the
+\fIrootpw\fR,
+\fItargetpw\fR
+and
+\fIrunaspw\fR
+flags in
+\fIsudoers\fR)
+.TP 6n
+\fR\&%U\fR
+expanded to the login name of the user the command will
+be run as (defaults to root)
+.TP 6n
+\fR%u\fR
+expanded to the invoking user's login name
+.TP 6n
+\fR%%\fR
+two consecutive
+\fR%\fR
+characters are collapsed into a single
+\fR%\fR
+character
+.PP
+On systems that use PAM for authentication,
+\fIpassprompt\fR
+will only be used if the prompt provided by the PAM module matches the string
+\(lqPassword: \(rq
+or
+\(lqusername's Password: \(rq.
+This ensures that the
+\fIpassprompt\fR
+setting does not interfere with challenge-response style authentication.
+The
+\fIpassprompt_override\fR
+flag can be used to change this behavior.
+.sp
+The default value is
+\(lq\fR@passprompt@\fR\(rq.
+.RE
+.if \n(PS \{\
+.TP 18n
+privs
+The default Solaris privileges to use when constructing a new
+privilege set for a command.
+This is passed to the executing process via the inherited privilege set,
+but is bounded by the limit privileges.
+If the
+\fIprivs\fR
+option is specified but the
+\fIlimitprivs\fR
+option is not, the limit privileges of the executing process is set to
+\fIprivs\fR.
+The default privileges may be overridden on a per-command basis in
+\fIsudoers\fR.
+This option is only available if
+\fBsudoers\fR
+is built on Solaris 10 or higher.
+.\}
+.if \n(SL \{\
+.TP 18n
+role
+The default SELinux role to use when constructing a new security
+context to run the command.
+The default role may be overridden on a per-command basis in the
+\fIsudoers\fR
+file or via command line options.
+This option is only available when
+\fBsudo\fR
+is built with SELinux support.
+.\}
+.TP 18n
+runas_default
+The default user to run commands as if the
+\fB\-u\fR
+option is not specified on the command line.
+This defaults to
+\fR@runas_default@\fR.
+.TP 18n
+sudoers_locale
+Locale to use when parsing the sudoers file, logging commands, and
+sending email.
+Note that changing the locale may affect how sudoers is interpreted.
+Defaults to
+\(lq\fRC\fR\(rq.
+.TP 18n
+timestamp_type
+\fBsudoers\fR
+uses per-user time stamp files for credential caching.
+The
+\fItimestamp_type\fR
+option can be used to specify the type of time stamp record used.
+It has the following possible values:
+.PP
+.RS 18n
+.PD 0
+.TP 8n
+global
+A single time stamp record is used for all of a user's login sessions,
+regardless of the terminal or parent process ID.
+An additional record is used to serialize password prompts when
+\fBsudo\fR
+is used multiple times in a pipeline, but this does not affect authentication.
+.PD
+.TP 8n
+ppid
+A single time stamp record is used for all processes with the same parent
+process ID (usually the shell).
+Commands run from the same shell (or other common parent process)
+will not require a password for
+\fItimestamp_timeout\fR
+minutes
+(\fR@timeout@\fR
+by default)
+\&.
+Commands run via
+\fBsudo\fR
+with a different parent process ID, for example from a shell script,
+will be authenticated separately.
+.TP 8n
+tty
+One time stamp record is used for each terminal,
+which means that a user's login sessions are authenticated separately.
+If no terminal is present, the behavior is the same as
+\fIppid\fR.
+Commands run from the same terminal will not require a password for
+\fItimestamp_timeout\fR
+minutes
+(\fR@timeout@\fR
+by default)
+\&.
+.TP 8n
+kernel
+The time stamp is stored in the kernel as an attribute of the terminal
+device.
+If no terminal is present, the behavior is the same as
+\fIppid\fR.
+Negative
+\fItimestamp_timeout\fR
+values are not supported and positive values are limited to a maximum
+of 60 minutes.
+This is currently only supported on
+OpenBSD.
+.PP
+The default value is
+\fI@timestamp_type@\fR.
+.sp
+This setting is only supported by version 1.8.21 or higher.
+.RE
+.TP 18n
+timestampdir
+The directory in which
+\fBsudo\fR
+stores its time stamp files.
+This directory should be cleared when the system reboots.
+The default is
+\fI@rundir@/ts\fR.
+.TP 18n
+timestampowner
+The owner of the lecture status directory, time stamp directory and all
+files stored therein.
+The default is
+\fRroot\fR.
+.if \n(SL \{\
+.TP 18n
+type
+The default SELinux type to use when constructing a new security
+context to run the command.
+The default type may be overridden on a per-command basis in the
+\fIsudoers\fR
+file or via command line options.
+This option is only available when
+\fBsudo\fR
+is built with SELinux support.
+.PP
+\fBStrings that can be used in a boolean context\fR:
+.TP 14n
+env_file
+The
+\fIenv_file\fR
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+\(lq\fRVARIABLE=value\fR\(rq
+or
+\(lq\fRexport VARIABLE=value\fR\(rq.
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+This file is considered to be part of the security policy,
+its contents are not subject to other
+\fBsudo\fR
+environment restrictions such as
+\fIenv_keep\fR
+and
+\fIenv_check\fR.
+.TP 14n
+exempt_group
+Users in this group are exempt from password and PATH requirements.
+The group name specified should not include a
+\fR%\fR
+prefix.
+This is not set by default.
+.TP 14n
+fdexec
+Determines whether
+\fBsudo\fR
+will execute a command by its path or by an open file descriptor.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+always
+Always execute by file descriptor.
+.PD
+.TP 8n
+never
+Never execute by file descriptor.
+.TP 8n
+digest_only
+Only execute by file descriptor if the command has an associated digest
+in the
+\fIsudoers\fR
+file.
+.PP
+The default value is
+\fIdigest_only\fR.
+This avoids a time of check versus time of use race condition when
+the command is located in a directory writable by the invoking user.
+.sp
+Note that
+\fIfdexec\fR
+will change the first element of the argument vector for scripts
+($0 in the shell) due to the way the kernel runs script interpreters.
+Instead of being a normal path, it will refer to a file descriptor.
+For example,
+\fI/dev/fd/4\fR
+on Solaris and
+\fI/proc/self/fd/4\fR
+on Linux.
+A workaround is to use the
+\fRSUDO_COMMAND\fR
+environment variable instead.
+.sp
+The
+\fIfdexec\fR
+setting is only used when the command is matched by path name.
+It has no effect if the command is matched by the built-in
+\fBALL\fR
+alias.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+If the operating system does not support the
+fexecve(2)
+system call, this setting has no effect.
+.RE
+.TP 14n
+group_plugin
+A string containing a
+\fBsudoers\fR
+group plugin with optional arguments.
+The string should consist of the plugin
+path, either fully-qualified or relative to the
+\fI@plugindir@\fR
+directory, followed by any configuration arguments the plugin requires.
+These arguments (if any) will be passed to the plugin's initialization function.
+If arguments are present, the string must be enclosed in double quotes
+(\&"").
+.sp
+For more information see
+\fIGROUP PROVIDER PLUGINS\fR.
+.TP 14n
+lecture
+This option controls when a short lecture will be printed along with
+the password prompt.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+always
+Always lecture the user.
+.PD
+.TP 8n
+never
+Never lecture the user.
+.TP 8n
+once
+Only lecture the user the first time they run
+\fBsudo\fR.
+.PP
+If no value is specified, a value of
+\fIonce\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fI@lecture@\fR.
+.RE
+.TP 14n
+lecture_file
+Path to a file containing an alternate
+\fBsudo\fR
+lecture that will be used in place of the standard lecture if the named
+file exists.
+By default,
+\fBsudo\fR
+uses a built-in lecture.
+.TP 14n
+listpw
+This option controls when a password will be required when a user runs
+\fBsudo\fR
+with the
+\fB\-l\fR
+option.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 10n
+all
+All the user's
+\fIsudoers\fR
+file entries for the current host must have
+the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.PD
+.TP 10n
+always
+The user must always enter a password to use the
+\fB\-l\fR
+option.
+.TP 10n
+any
+At least one of the user's
+\fIsudoers\fR
+file entries for the current host
+must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.TP 10n
+never
+The user need never enter a password to use the
+\fB\-l\fR
+option.
+.PP
+If no value is specified, a value of
+\fIany\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fIany\fR.
+.RE
+.TP 14n
+log_format
+The event log format.
+Supported log formats are:
+.PP
+.RS 14n
+.PD 0
+.TP 10n
+json
+Logs in JSON format.
+JSON log entries contain the full user details as well as the execution
+environment if the command was allowed.
+Due to limitations of the protocol, JSON events sent via
+\fIsyslog\fR
+may be truncated.
+.PD
+.TP 10n
+sudo
+Traditional sudo-style logs, see
+\fILOG FORMAT\fR
+for a description of the log file format.
+.PP
+This setting affects logs sent via
+syslog(3)
+as well as the file specified by the
+\fIlogfile\fR
+setting, if any.
+The default value is
+\fIsudo\fR.
+.RE
+.TP 14n
+logfile
+Path to the
+\fBsudo\fR
+log file (not the syslog log file).
+Setting a path turns on logging to a file;
+negating this option turns it off.
+By default,
+\fBsudo\fR
+logs via syslog.
+.TP 14n
+mailerflags
+Flags to use when invoking mailer.
+Defaults to
+\fB\-t\fR.
+.TP 14n
+mailerpath
+Path to mail program used to send warning mail.
+Defaults to the path to sendmail found at configure time.
+.TP 14n
+mailfrom
+Address to use for the
+\(lqfrom\(rq
+address when sending warning and error mail.
+The address should be enclosed in double quotes
+(\&"")
+to protect against
+\fBsudo\fR
+interpreting the
+\fR@\fR
+sign.
+Defaults to the name of the user running
+\fBsudo\fR.
+.TP 14n
+mailto
+Address to send warning and error mail to.
+The address should be enclosed in double quotes
+(\&"")
+to protect against
+\fBsudo\fR
+interpreting the
+\fR@\fR
+sign.
+Defaults to
+\fR@mailto@\fR.
+.TP 14n
+restricted_env_file
+The
+\fIrestricted_env_file\fR
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+\(lq\fRVARIABLE=value\fR\(rq
+or
+\(lq\fRexport VARIABLE=value\fR\(rq.
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+Unlike
+\fIenv_file\fR,
+the file's contents are not trusted and are processed in a manner
+similar to that of the invoking user's environment.
+If
+\fIenv_reset\fR
+is enabled, variables in the file will only be added if they are
+matched by either the
+\fIenv_check\fR
+or
+\fIenv_keep\fR
+list.
+If
+\fIenv_reset\fR
+is disabled, variables in the file are added as long as they
+are not matched by the
+\fIenv_delete\fR
+list.
+In either case, the contents of
+\fIrestricted_env_file\fR
+are processed before the contents of
+\fIenv_file\fR.
+.TP 14n
+runchroot
+If set,
+\fBsudo\fR
+will use this value for the root directory when running a command.
+The special value
+\(lq*\(rq
+will allow the user to specify the root directory via
+\fBsudo\fR's
+\fB\-R\fR
+option.
+See the
+\fIChroot_Spec\fR
+section for more details.
+.sp
+It is only possible to use
+\fIrunchroot\fR
+as a command-specific Defaults setting if the command exists with
+the same path both inside and outside the chroot jail.
+This restriction does not apply to generic, host or user-based
+Defaults settings or to a
+\fICmnd_Spec\fR
+that includes a
+\fIChroot_Spec\fR.
+.sp
+This setting is only supported by version 1.9.3 or higher.
+.TP 14n
+runcwd
+If set,
+\fBsudo\fR
+will use this value for the working directory when running a command.
+The special value
+\(lq*\(rq
+will allow the user to specify the working directory via
+\fBsudo\fR's
+\fB\-D\fR
+option.
+See the
+\fIChdir_Spec\fR
+section for more details.
+.sp
+This setting is only supported by version 1.9.3 or higher.
+.TP 14n
+secure_path
+If set,
+\fBsudo\fR
+will use this value in place of the user's
+\fRPATH\fR
+environment variable.
+This option can be used to reset the
+\fRPATH\fR
+to a known good value that contains directories for system administrator
+commands such as
+\fI/usr/sbin\fR.
+.sp
+Users in the group specified by the
+\fIexempt_group\fR
+option are not affected by
+\fIsecure_path\fR.
+This option is @secure_path@ by default.
+.TP 14n
+syslog
+Syslog facility if syslog is being used for logging (negate to
+disable syslog logging).
+Defaults to
+\fR@logfac@\fR.
+.sp
+The following syslog facilities are supported:
+\fBauthpriv\fR
+(if your
+OS supports it),
+\fBauth\fR,
+\fBdaemon\fR,
+\fBuser\fR,
+\fBlocal0\fR,
+\fBlocal1\fR,
+\fBlocal2\fR,
+\fBlocal3\fR,
+\fBlocal4\fR,
+\fBlocal5\fR,
+\fBlocal6\fR,
+and
+\fBlocal7\fR.
+.TP 14n
+syslog_badpri
+.br
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to
+\fR@badpri@\fR.
+.sp
+The following syslog priorities are supported:
+\fBalert\fR,
+\fBcrit\fR,
+\fBdebug\fR,
+\fBemerg\fR,
+\fBerr\fR,
+\fBinfo\fR,
+\fBnotice\fR,
+\fBwarning\fR,
+and
+\fBnone\fR.
+Negating the option or setting it to a value of
+\fBnone\fR
+will disable logging of unsuccessful commands.
+.TP 14n
+syslog_goodpri
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to
+\fR@goodpri@\fR.
+.sp
+See
+\fIsyslog_badpri\fR
+for the list of supported syslog priorities.
+Negating the option or setting it to a value of
+\fBnone\fR
+will disable logging of successful commands.
+.TP 14n
+verifypw
+This option controls when a password will be required when a user runs
+\fBsudo\fR
+with the
+\fB\-v\fR
+option.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+all
+All the user's
+\fIsudoers\fR
+file entries for the current host must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.PD
+.TP 8n
+always
+The user must always enter a password to use the
+\fB\-v\fR
+option.
+.TP 8n
+any
+At least one of the user's
+\fIsudoers\fR
+file entries for the current host must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.TP 8n
+never
+The user need never enter a password to use the
+\fB\-v\fR
+option.
+.PP
+If no value is specified, a value of
+\fIall\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fIall\fR.
+.RE
+.PP
+\fBLists that can be used in a boolean context\fR:
+.\}
+.TP 18n
+env_check
+Environment variables to be removed from the user's environment
+unless they are considered
+\(lqsafe\(rq.
+For all variables except
+\fRTZ\fR,
+\(lqsafe\(rq
+means that the variable's value does not contain any
+\(oq%\(cq
+or
+\(oq/\(cq
+characters.
+This can be used to guard against printf-style format vulnerabilities
+in poorly-written programs.
+The
+\fRTZ\fR
+variable is considered unsafe if any of the following are true:
+.PP
+.RS 18n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+It consists of a fully-qualified path name,
+optionally prefixed with a colon
+(\(oq:\&\(cq),
+that does not match the location of the
+\fIzoneinfo\fR
+directory.
+.PD
+.TP 3n
+\fB\(bu\fR
+It contains a
+\fI..\fR
+path element.
+.TP 3n
+\fB\(bu\fR
+It contains white space or non-printable characters.
+.TP 3n
+\fB\(bu\fR
+It is longer than the value of
+\fRPATH_MAX\fR.
+.PP
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using
+the
+\fR=\fR,
+\fR+=\fR,
+\fR-=\fR,
+and
+\fR\&!\fR
+operators respectively.
+Regardless of whether the
+\fRenv_reset\fR
+option is enabled or disabled, variables specified by
+\fRenv_check\fR
+will be preserved in the environment if they pass the aforementioned check.
+The global list of environment variables to check is displayed when
+\fBsudo\fR
+is run by root with
+the
+\fB\-V\fR
+option.
+.RE
+.TP 18n
+env_delete
+Environment variables to be removed from the user's environment when the
+\fIenv_reset\fR
+option is not in effect.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+\fR=\fR,
+\fR+=\fR,
+\fR-=\fR,
+and
+\fR\&!\fR
+operators respectively.
+The global list of environment variables to remove is displayed when
+\fBsudo\fR
+is run by root with the
+\fB\-V\fR
+option.
+Note that many operating systems will remove potentially dangerous
+variables from the environment of any set-user-ID process (such as
+\fBsudo\fR).
+.TP 18n
+env_keep
+Environment variables to be preserved in the user's environment when the
+\fIenv_reset\fR
+option is in effect.
+This allows fine-grained control over the environment
+\fBsudo\fR-spawned
+processes will receive.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+\fR=\fR,
+\fR+=\fR,
+\fR-=\fR,
+and
+\fR\&!\fR
+operators respectively.
+The global list of variables to keep
+is displayed when
+\fBsudo\fR
+is run by root with the
+\fB\-V\fR
+option.
+.sp
+Preserving the
+\fRHOME\fR
+environment variable has security implications since many programs use it
+when searching for configuration or data files.
+Adding
+\fRHOME\fR
+to
+\fIenv_keep\fR
+may enable a user to run unrestricted commands via
+\fBsudo\fR
+and is strongly discouraged.
+Users wishing to edit files with
+\fBsudo\fR
+should run
+\fBsudoedit\fR
+(or
+\fBsudo\fR \fB\-e\fR)
+to get their accustomed editor configuration instead of
+invoking the editor directly.
+.TP 18n
+log_servers
+A list of one or more servers to use for remote event and I/O log storage,
+separated by white space.
+Log servers must be running
+\fBsudo_logsrvd\fR
+or another service that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.sp
+Server addresses should be of the form
+\(lqhost[:port][(tls)]\(rq.
+The host portion may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+.sp
+If the optional
+\fItls\fR
+flag is present, the connection will be secured
+with Transport Layer Security (TLS) version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+.sp
+If a port is specified, it may either be a port number or a well-known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.sp
+When
+\fIlog_servers\fR
+is set, event log data will be logged both locally (see the
+\fIsyslog\fR
+and
+\fIlog_file\fR
+settings) as well as remotely, but I/O log data will only be logged remotely.
+If multiple hosts are specified, they will be attempted in reverse order.
+If no log servers are available, the user will not be able to run
+a command unless either the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+Likewise, if the connection to the log server is interrupted while
+\fBsudo\fR
+is running, the command will be terminated unless the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.SH "GROUP PROVIDER PLUGINS"
+The
+\fBsudoers\fR
+plugin supports its own plugin interface to allow non-Unix
+group lookups which can query a group source other
+than the standard Unix group database.
+This can be used to implement support for the
+\fRnonunix_group\fR
+syntax described earlier.
+.PP
+Group provider plugins are specified via the
+\fIgroup_plugin\fR
+setting.
+The argument to
+\fIgroup_plugin\fR
+should consist of the plugin path, either fully-qualified or relative to the
+\fI@plugindir@\fR
+directory, followed by any configuration options the plugin requires.
+These options (if specified) will be passed to the plugin's initialization
+function.
+If options are present, the string must be enclosed in double quotes
+(\&"").
+.PP
+The following group provider plugins are installed by default:
+.TP 10n
+group_file
+The
+\fIgroup_file\fR
+plugin supports an alternate group file that uses the same syntax as the
+\fI/etc/group\fR
+file.
+The path to the group file should be specified as an option
+to the plugin.
+For example, if the group file to be used is
+\fI/etc/sudo-group\fR:
+.nf
+.sp
+.RS 10n
+Defaults group_plugin="group_file.so /etc/sudo-group"
+.RE
+.fi
+.TP 10n
+system_group
+The
+\fIsystem_group\fR
+plugin supports group lookups via the standard C library functions
+\fBgetgrnam\fR()
+and
+\fBgetgrid\fR().
+This plugin can be used in instances where the user belongs to
+groups not present in the user's supplemental group vector.
+This plugin takes no options:
+.nf
+.sp
+.RS 10n
+Defaults group_plugin=system_group.so
+.RE
+.fi
+.PP
+The group provider plugin API is described in detail in
+sudo_plugin(@mansectform@).
+.SH "LOG FORMAT"
+\fBsudoers\fR
+can log events in either JSON or
+\fIsudo\fR
+format,
+this section describes the
+\fIsudo\fR
+log format.
+Depending on
+\fIsudoers\fR
+configuration,
+\fBsudoers\fR
+can log events via
+syslog(3),
+to a local log file, or both.
+The log format is almost identical in both cases.
+.SS "Accepted command log entries"
+Commands that sudo runs are logged using the following format (split
+into multiple lines for readability):
+.nf
+.sp
+.RS 4n
+date hostname progname: username : TTY=ttyname ; PWD=cwd ; \e
+ USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
+ ENV=env_vars COMMAND=command
+.RE
+.fi
+.PP
+Where the fields are as follows:
+.TP 14n
+date
+The date the command was run.
+Typically, this is in the format
+\(lqMMM, DD, HH:MM:SS\(rq.
+If logging via
+syslog(3),
+the actual date format is controlled by the syslog daemon.
+If logging to a file and the
+\fIlog_year\fR
+option is enabled,
+the date will also include the year.
+.TP 14n
+hostname
+The name of the host
+\fBsudo\fR
+was run on.
+This field is only present when logging via
+syslog(3).
+.TP 14n
+progname
+The name of the program, usually
+\fIsudo\fR
+or
+\fIsudoedit\fR.
+This field is only present when logging via
+syslog(3).
+.TP 14n
+username
+The login name of the user who ran
+\fBsudo\fR.
+.TP 14n
+ttyname
+The short name of the terminal (e.g.,
+\(lqconsole\(rq,
+\(lqtty01\(rq,
+or
+\(lqpts/0\(rq)
+\fBsudo\fR
+was run on, or
+\(lqunknown\(rq
+if there was no terminal present.
+.TP 14n
+cwd
+The current working directory that
+\fBsudo\fR
+was run in.
+.TP 14n
+runasuser
+The user the command was run as.
+.TP 14n
+runasgroup
+The group the command was run as if one was specified on the command line.
+.TP 14n
+logid
+An I/O log identifier that can be used to replay the command's output.
+This is only present when the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+option is enabled.
+.TP 14n
+env_vars
+A list of environment variables specified on the command line,
+if specified.
+.TP 14n
+command
+The actual command that was executed.
+.PP
+Messages are logged using the locale specified by
+\fIsudoers_locale\fR,
+which defaults to the
+\(lq\fRC\fR\(rq
+locale.
+.SS "Denied command log entries"
+If the user is not allowed to run the command, the reason for the denial
+will follow the user name.
+Possible reasons include:
+.TP 3n
+user NOT in sudoers
+The user is not listed in the
+\fIsudoers\fR
+file.
+.TP 3n
+user NOT authorized on host
+The user is listed in the
+\fIsudoers\fR
+file but is not allowed to run commands on the host.
+.TP 3n
+command not allowed
+The user is listed in the
+\fIsudoers\fR
+file for the host but they are not allowed to run the specified command.
+.TP 3n
+3 incorrect password attempts
+The user failed to enter their password after 3 tries.
+The actual number of tries will vary based on the number of
+failed attempts and the value of the
+\fIpasswd_tries\fR
+option.
+.TP 3n
+a password is required
+The
+\fB\-n\fR
+option was specified but a password was required.
+.TP 3n
+sorry, you are not allowed to set the following environment variables
+The user specified environment variables on the command line that
+were not allowed by
+\fIsudoers\fR.
+.SS "Error log entries"
+If an error occurs,
+\fBsudoers\fR
+will log a message and, in most cases, send a message to the
+administrator via email.
+Possible errors include:
+.TP 3n
+parse error in @sysconfdir@/sudoers near line N
+\fBsudoers\fR
+encountered an error when parsing the specified file.
+In some cases, the actual error may be one line above or below the
+line number listed, depending on the type of error.
+.TP 3n
+problem with defaults entries
+The
+\fIsudoers\fR
+file contains one or more unknown Defaults settings.
+This does not prevent
+\fBsudo\fR
+from running, but the
+\fIsudoers\fR
+file should be checked using
+\fBvisudo\fR.
+.TP 3n
+timestamp owner (username): \&No such user
+The time stamp directory owner, as specified by the
+\fItimestampowner\fR
+setting, could not be found in the password database.
+.TP 3n
+unable to open/read @sysconfdir@/sudoers
+The
+\fIsudoers\fR
+file could not be opened for reading.
+This can happen when the
+\fIsudoers\fR
+file is located on a remote file system that maps user-ID 0 to
+a different value.
+Normally,
+\fBsudoers\fR
+tries to open the
+\fIsudoers\fR
+file using group permissions to avoid this problem.
+Consider either changing the ownership of
+\fI@sysconfdir@/sudoers\fR
+or adding an argument like
+\(lqsudoers_uid=N\(rq
+(where
+\(oqN\(cq
+is the user-ID that owns the
+\fIsudoers\fR
+file) to the end of the
+\fBsudoers\fR
+\fRPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+unable to stat @sysconfdir@/sudoers
+The
+\fI@sysconfdir@/sudoers\fR
+file is missing.
+.TP 3n
+@sysconfdir@/sudoers is not a regular file
+The
+\fI@sysconfdir@/sudoers\fR
+file exists but is not a regular file or symbolic link.
+.TP 3n
+@sysconfdir@/sudoers is owned by uid N, should be 0
+The
+\fIsudoers\fR
+file has the wrong owner.
+If you wish to change the
+\fIsudoers\fR
+file owner, please add
+\(lqsudoers_uid=N\(rq
+(where
+\(oqN\(cq
+is the user-ID that owns the
+\fIsudoers\fR
+file) to the
+\fBsudoers\fR
+\fRPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+@sysconfdir@/sudoers is world writable
+The permissions on the
+\fIsudoers\fR
+file allow all users to write to it.
+The
+\fIsudoers\fR
+file must not be world-writable, the default file mode
+is 0440 (readable by owner and group, writable by none).
+The default mode may be changed via the
+\(lqsudoers_mode\(rq
+option to the
+\fBsudoers\fR
+\fRPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+@sysconfdir@/sudoers is owned by gid N, should be 1
+The
+\fIsudoers\fR
+file has the wrong group ownership.
+If you wish to change the
+\fIsudoers\fR
+file group ownership, please add
+\(lqsudoers_gid=N\(rq
+(where
+\(oqN\(cq
+is the group-ID that owns the
+\fIsudoers\fR
+file) to the
+\fBsudoers\fR
+\fRPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+unable to open @rundir@/ts/username
+\fBsudoers\fR
+was unable to read or create the user's time stamp file.
+This can happen when
+\fItimestampowner\fR
+is set to a user other than root and the mode on
+\fI@rundir@\fR
+is not searchable by group or other.
+The default mode for
+\fI@rundir@\fR
+is 0711.
+.TP 3n
+unable to write to @rundir@/ts/username
+\fBsudoers\fR
+was unable to write to the user's time stamp file.
+.TP 3n
+@rundir@/ts is owned by uid X, should be Y
+The time stamp directory is owned by a user other than
+\fItimestampowner\fR.
+This can occur when the value of
+\fItimestampowner\fR
+has been changed.
+\fBsudoers\fR
+will ignore the time stamp directory until the owner is corrected.
+.TP 3n
+@rundir@/ts is group writable
+The time stamp directory is group-writable; it should be writable only by
+\fItimestampowner\fR.
+The default mode for the time stamp directory is 0700.
+\fBsudoers\fR
+will ignore the time stamp directory until the mode is corrected.
+.SS "Notes on logging via syslog"
+By default,
+\fBsudoers\fR
+logs messages via
+syslog(3).
+The
+\fIdate\fR,
+\fIhostname\fR,
+and
+\fIprogname\fR
+fields are added by the system's
+\fBsyslog\fR()
+function, not
+\fBsudoers\fR
+itself.
+As such, they may vary in format on different systems.
+.PP
+The maximum size of syslog messages varies from system to system.
+The
+\fIsyslog_maxlen\fR
+setting can be used to change the maximum syslog message size
+from the default value of 980 bytes.
+For more information, see the description of
+\fIsyslog_maxlen\fR.
+.SS "Notes on logging to a file"
+If the
+\fIlogfile\fR
+option is set,
+\fBsudoers\fR
+will log to a local file, such as
+\fI/var/log/sudo\fR.
+When logging to a file,
+\fBsudoers\fR
+uses a format similar to
+syslog(3),
+with a few important differences:
+.TP 5n
+1.\&
+The
+\fIprogname\fR
+and
+\fIhostname\fR
+fields are not present.
+.TP 5n
+2.\&
+If the
+\fIlog_year\fR
+option is enabled,
+the date will also include the year.
+.TP 5n
+3.\&
+Lines that are longer than
+\fIloglinelen\fR
+characters (80 by default) are word-wrapped and continued on the
+next line with a four character indent.
+This makes entries easier to read for a human being, but makes it
+more difficult to use
+grep(1)
+on the log files.
+If the
+\fIloglinelen\fR
+option is set to 0 (or negated with a
+\(oq\&!\(cq),
+word wrap will be disabled.
+.SH "I/O LOG FILES"
+When I/O logging is enabled,
+\fBsudo\fR
+will run the command in a pseudo-terminal and log all user input and/or output,
+depending on which options are enabled.
+I/O can be logged either to the local machine or to a remote log server.
+For local logs, I/O is logged to the directory specified by the
+\fIiolog_dir\fR
+option
+(\fI@iolog_dir@\fR
+by default)
+using a unique session ID that is included in the
+\fBsudo\fR
+log line, prefixed with
+\(lq\fRTSID=\fR\(rq.
+The
+\fIiolog_file\fR
+option may be used to control the format of the session ID.
+For remote logs, the
+\fIlog_servers\fR
+setting is used to specify one or more log servers running
+\fBsudo_logsrvd\fR
+or another server that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.PP
+For both local and remote I/O logs, each log is stored in a separate
+directory that contains the following files:
+.TP 10n
+\fIlog\fR
+A text file containing information about the command.
+The first line consists of the following colon-delimited fields:
+the time the command was run, the name of the user
+who ran
+\fBsudo\fR,
+the name of the target user, the name of the target group (optional),
+the terminal that
+\fBsudo\fR
+was run from, and the number of lines and columns of the terminal.
+The second and third lines contain the working directory the command
+was run from and the path name of the command itself (with arguments
+if present).
+.TP 10n
+\fIlog.json\fR
+A JSON-formatted file containing information about the command.
+This is similar to the
+\fIlog\fR
+file but contains additional information and is easily extensible.
+The
+\fIlog.json\fR
+file will be used by
+sudoreplay(@mansectsu@)
+in preference to the
+\fIlog\fR
+file if it exists.
+The file may contain the following elements:
+.PP
+.RS 10n
+.PD 0
+.TP 10n
+timestamp
+.br
+A JSON object containing time the command was run.
+It consists of two values,
+\fIseconds\fR
+and
+\fInanoseconds\fR.
+.PD
+.TP 10n
+columns
+The number of columns of the terminal the command ran on, or zero
+if no terminal was present.
+.TP 10n
+command
+The fully-qualified path of the command that was run.
+.TP 10n
+lines
+The number of lines of the terminal the command ran on, or zero
+if no terminal was present.
+.TP 10n
+runargv
+A JSON array representing the command's argument vector as passed to the
+execve(2)
+system call.
+.TP 10n
+runenv
+A JSON array representing the command's environment as passed to the
+execve(2)
+system call.
+.TP 10n
+rungid
+The group ID the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.TP 10n
+rungroup
+The name of the group the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.TP 10n
+runuid
+The user ID the command ran as.
+.TP 10n
+runuser
+The name of the user the command ran as.
+.TP 10n
+submitcwd
+.br
+The current working directory at the time
+\fBsudo\fR
+was run.
+.TP 10n
+submithost
+The name of the host the command was run on.
+.TP 10n
+submituser
+The name of the user who ran the command via
+\fBsudo\fR.
+.TP 10n
+ttyname
+The path name of the terminal the user invoked
+\fBsudo\fR
+from.
+If the command was run in a pseudo-terminal,
+\fIttyname\fR
+will be different from the terminal the command actually ran in.
+.PD 0
+.PP
+.RE
+.PD
+.TP 10n
+\fItiming\fR
+Timing information used to replay the session.
+Each line consists of the I/O log entry type and amount of time
+since the last entry, followed by type-specific data.
+The I/O log entry types and their corresponding type-specific data are:
+.PP
+.RS 10n
+.PD 0
+.TP 6n
+0
+standard input, number of bytes in the entry
+.TP 6n
+1
+standard output, number of bytes in the entry
+.TP 6n
+2
+standard error, number of bytes in the entry
+.TP 6n
+3
+terminal input, number of bytes in the entry
+.TP 6n
+4
+terminal output, number of bytes in the entry
+.TP 6n
+5
+window change, new number lines and columns
+.TP 6n
+6
+bug compatibility for
+\fBsudo\fR
+1.8.7 terminal output
+.TP 6n
+7
+command suspend or resume, signal received
+.PP
+.RE
+.PD
+.TP 10n
+\fIttyin\fR
+Raw input from the user's terminal, exactly as it was received.
+No post-processing is performed.
+For manual viewing, you may wish to convert carriage return characters
+in the log to line feeds.
+For example:
+\(oqgunzip -c ttyin | tr \&"\er\&" \&"\en\&"\(cq
+.TP 10n
+\fIstdin\fR
+The standard input when no terminal is present, or input redirected from
+a pipe or file.
+.TP 10n
+\fIttyout\fR
+Output from the pseudo-terminal (what the command writes to the screen).
+Note that terminal-specific post-processing is performed before the
+data is logged.
+This means that, for example, line feeds are usually converted to
+line feed/carriage return pairs and tabs may be expanded to spaces.
+.TP 10n
+\fIstdout\fR
+The standard output when no terminal is present, or output redirected to
+a pipe or file.
+.TP 10n
+\fIstderr\fR
+The standard error redirected to a pipe or file.
+.PP
+All files other than
+\fIlog\fR
+are compressed in gzip format unless the
+\fIcompress_io\fR
+flag has been disabled.
+Due to buffering, it is not normally possible to display the I/O logs in
+real-time as the program is executing.
+The I/O log data will not be complete until the program run by
+\fBsudo\fR
+has exited or has been terminated by a signal.
+The
+\fIiolog_flush\fR
+flag can be used to disable buffering, in which case I/O log data
+is written to disk as soon as it is available.
+The output portion of an I/O log file can be viewed with the
+sudoreplay(@mansectsu@)
+utility, which can also be used to list or search the available logs.
+.PP
+Note that user input may contain sensitive information such as
+passwords (even if they are not echoed to the screen), which will
+be stored in the log file unencrypted.
+In most cases, logging the command output via
+\fIlog_output\fR
+or
+\fRLOG_OUTPUT\fR
+is all that is required.
+.PP
+Since each session's I/O logs are stored in a separate directory,
+traditional log rotation utilities cannot be used to limit the
+number of I/O logs.
+The simplest way to limit the number of I/O is by setting the
+\fImaxseq\fR
+option to the maximum number of logs you wish to store.
+Once the I/O log sequence number reaches
+\fImaxseq\fR,
+it will be reset to zero and
+\fBsudoers\fR
+will truncate and re-use any existing I/O logs.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front end configuration
+.TP 26n
+\fI@sysconfdir@/sudoers\fR
+List of who can run what
+.TP 26n
+\fI/etc/group\fR
+Local groups file
+.TP 26n
+\fI/etc/netgroup\fR
+List of network groups
+.TP 26n
+\fI@iolog_dir@\fR
+I/O log files
+.TP 26n
+\fI@rundir@/ts\fR
+Directory containing time stamps for the
+\fBsudoers\fR
+security policy
+.TP 26n
+\fI@vardir@/lectured\fR
+Directory containing lecture status files for the
+\fBsudoers\fR
+security policy
+.TP 26n
+\fI/etc/environment\fR
+Initial environment for
+\fB\-i\fR
+mode on AIX and Linux systems
+.SH "EXAMPLES"
+Below are example
+\fIsudoers\fR
+file entries.
+Admittedly, some of these are a bit contrived.
+First, we allow a few environment variables to pass and then define our
+\fIaliases\fR:
+.nf
+.sp
+.RS 0n
+# Run X applications through sudo; HOME is used to find the
+# .Xauthority file. Note that other programs use HOME to find
+# configuration files and this may lead to privilege escalation!
+Defaults env_keep += "DISPLAY HOME"
+
+# User alias specification
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+# Runas alias specification
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+Runas_Alias ADMINGRP = adm, oper
+
+# Host alias specification
+Host_Alias SPARC = bigtime, eclipse, moet, anchor :\e
+ SGI = grolsch, dandelion, black :\e
+ ALPHA = widget, thalamus, foobar :\e
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+# Cmnd alias specification
+Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e
+ /usr/sbin/restore, /usr/sbin/rrestore,\e
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh,\e
+ /usr/local/bin/tcsh, /usr/bin/rsh,\e
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+.RE
+.fi
+.PP
+Here we override some of the compiled in default values.
+We want
+\fBsudo\fR
+to log via
+syslog(3)
+using the
+\fIauth\fR
+facility in all cases and for commands to be run with
+the target user's home directory as the working directory.
+We don't want to subject the full time staff to the
+\fBsudo\fR
+lecture and we want to allow them to run commands in a
+chroot(2)
+\(lqsandbox\(rq
+via the
+\fB\-R\fR
+option.
+User
+\fBmillert\fR
+need not provide a password and we don't want to reset the
+\fRLOGNAME\fR
+or
+\fRUSER\fR
+environment variables when running commands as root.
+Additionally, on the machines in the
+\fISERVERS\fR
+\fRHost_Alias\fR,
+we keep an additional local log file and make sure we log the year
+in each log line since the log entries will be kept around for several years.
+Lastly, we disable shell escapes for the commands in the PAGERS
+\fRCmnd_Alias\fR
+(\fI/usr/bin/more\fR,
+\fI/usr/bin/pg\fR
+and
+\fI/usr/bin/less\fR)
+\&.
+Note that this will not effectively constrain users with
+\fBsudo\fR
+\fBALL\fR
+privileges.
+.nf
+.sp
+.RS 0n
+# Override built-in defaults
+Defaults syslog=auth,runcwd=~
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture,runchroot=*
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+.RE
+.fi
+.PP
+The
+\fIUser specification\fR
+is the part that actually determines who may run what.
+.nf
+.sp
+.RS 0n
+root ALL = (ALL) ALL
+%wheel ALL = (ALL) ALL
+.RE
+.fi
+.PP
+We let
+\fBroot\fR
+and any user in group
+\fBwheel\fR
+run any command on any host as any user.
+.nf
+.sp
+.RS 0n
+FULLTIMERS ALL = NOPASSWD: ALL
+.RE
+.fi
+.PP
+Full time sysadmins
+(\fBmillert\fR,
+\fBmikef\fR,
+and
+\fBdowdy\fR)
+may run any command on any host without authenticating themselves.
+.nf
+.sp
+.RS 0n
+PARTTIMERS ALL = ALL
+.RE
+.fi
+.PP
+Part time sysadmins
+\fBbostley\fR,
+\fBjwfox\fR,
+and
+\fBcrawl\fR)
+may run any command on any host but they must authenticate themselves
+first (since the entry lacks the
+\fRNOPASSWD\fR
+tag).
+.nf
+.sp
+.RS 0n
+jack CSNETS = ALL
+.RE
+.fi
+.PP
+The user
+\fBjack\fR
+may run any command on the machines in the
+\fICSNETS\fR
+alias (the networks
+\fR128.138.243.0\fR,
+\fR128.138.204.0\fR,
+and
+\fR128.138.242.0\fR).
+Of those networks, only
+\fR128.138.204.0\fR
+has an explicit netmask (in CIDR notation) indicating it is a class C network.
+For the other networks in
+\fICSNETS\fR,
+the local machine's netmask will be used during matching.
+.nf
+.sp
+.RS 0n
+lisa CUNETS = ALL
+.RE
+.fi
+.PP
+The user
+\fBlisa\fR
+may run any command on any host in the
+\fICUNETS\fR
+alias (the class B network
+\fR128.138.0.0\fR).
+.nf
+.sp
+.RS 0n
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\e
+ sudoedit /etc/printcap, /usr/oper/bin/
+.RE
+.fi
+.PP
+The
+\fBoperator\fR
+user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory
+\fI/usr/oper/bin/\fR.
+Note that one command in the
+\fRDUMPS\fR
+Cmnd_Alias includes a sha224 digest,
+\fI/home/operator/bin/start_backups\fR.
+This is because the directory containing the script is writable by the
+operator user.
+If the script is modified (resulting in a digest mismatch) it will no longer
+be possible to run it via
+\fBsudo\fR.
+.nf
+.sp
+.RS 0n
+joe ALL = /usr/bin/su operator
+.RE
+.fi
+.PP
+The user
+\fBjoe\fR
+may only
+su(1)
+to operator.
+.nf
+.sp
+.RS 0n
+pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root*
+
+%opers ALL = (: ADMINGRP) /usr/sbin/
+.RE
+.fi
+.PP
+Users in the
+\fBopers\fR
+group may run commands in
+\fI/usr/sbin/\fR
+as themselves
+with any group in the
+\fIADMINGRP\fR
+\fRRunas_Alias\fR
+(the
+\fBadm\fR
+and
+\fBoper\fR
+groups).
+.PP
+The user
+\fBpete\fR
+is allowed to change anyone's password except for
+root on the
+\fIHPPA\fR
+machines.
+Because command line arguments are matched as a single,
+concatenated string, the
+\(oq*\(cq
+wildcard will match
+\fImultiple\fR
+words.
+This example assumes that
+passwd(1)
+does not take multiple user names on the command line.
+Note that on GNU systems, options to
+passwd(1)
+may be specified after the user argument.
+As a result, this rule will also allow:
+.nf
+.sp
+.RS 4n
+passwd username --expire
+.RE
+.fi
+.PP
+which may not be desirable.
+.nf
+.sp
+.RS 0n
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+.RE
+.fi
+.PP
+The user
+\fBbob\fR
+may run anything on the
+\fISPARC\fR
+and
+\fISGI\fR
+machines as any user listed in the
+\fIOP\fR
+\fRRunas_Alias\fR
+(\fBroot\fR
+and
+\fBoperator\fR.)
+.nf
+.sp
+.RS 0n
+jim +biglab = ALL
+.RE
+.fi
+.PP
+The user
+\fBjim\fR
+may run any command on machines in the
+\fIbiglab\fR
+netgroup.
+\fBsudo\fR
+knows that
+\(lqbiglab\(rq
+is a netgroup due to the
+\(oq+\(cq
+prefix.
+.nf
+.sp
+.RS 0n
++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+.RE
+.fi
+.PP
+Users in the
+\fBsecretaries\fR
+netgroup need to help manage the printers as well as add and remove users,
+so they are allowed to run those commands on all machines.
+.nf
+.sp
+.RS 0n
+fred ALL = (DB) NOPASSWD: ALL
+.RE
+.fi
+.PP
+The user
+\fBfred\fR
+can run commands as any user in the
+\fIDB\fR
+\fRRunas_Alias\fR
+(\fBoracle\fR
+or
+\fBsybase\fR)
+without giving a password.
+.nf
+.sp
+.RS 0n
+john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+.RE
+.fi
+.PP
+On the
+\fIALPHA\fR
+machines, user
+\fBjohn\fR
+may su to anyone except root but he is not allowed to specify any options
+to the
+su(1)
+command.
+.nf
+.sp
+.RS 0n
+jen ALL, !SERVERS = ALL
+.RE
+.fi
+.PP
+The user
+\fBjen\fR
+may run any command on any machine except for those in the
+\fISERVERS\fR
+\fRHost_Alias\fR
+(primary, mail, www and ns).
+.nf
+.sp
+.RS 0n
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+.RE
+.fi
+.PP
+For any machine in the
+\fISERVERS\fR
+\fRHost_Alias\fR,
+\fBjill\fR
+may run
+any commands in the directory
+\fI/usr/bin/\fR
+except for those commands
+belonging to the
+\fISU\fR
+and
+\fISHELLS\fR
+\fRCmnd_Aliases\fR.
+While not specifically mentioned in the rule, the commands in the
+\fIPAGERS\fR
+\fRCmnd_Alias\fR
+all reside in
+\fI/usr/bin\fR
+and have the
+\fInoexec\fR
+option set.
+.nf
+.sp
+.RS 0n
+steve CSNETS = (operator) /usr/local/op_commands/
+.RE
+.fi
+.PP
+The user
+\fBsteve\fR
+may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+.nf
+.sp
+.RS 0n
+matt valkyrie = KILL
+.RE
+.fi
+.PP
+On his personal workstation, valkyrie,
+\fBmatt\fR
+needs to be able to kill hung processes.
+.nf
+.sp
+.RS 0n
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+.RE
+.fi
+.PP
+On the host www, any user in the
+\fIWEBADMIN\fR
+\fRUser_Alias\fR
+(will, wendy, and wim), may run any command as user www (which owns the
+web pages) or simply
+su(1)
+to www.
+.nf
+.sp
+.RS 0n
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\e
+ /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM
+.RE
+.fi
+.PP
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+\fRHost_Alias\fR
+(orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candidate
+for encapsulating in a shell script.
+.SH "SECURITY NOTES"
+.SS "Limitations of the \(oq!\&\(cq operator"
+It is generally not effective to
+\(lqsubtract\(rq
+commands from
+\fBALL\fR
+using the
+\(oq!\&\(cq
+operator.
+A user can trivially circumvent this by copying the desired command
+to a different name and then executing that.
+For example:
+.nf
+.sp
+.RS 0n
+bill ALL = ALL, !SU, !SHELLS
+.RE
+.fi
+.PP
+Doesn't really prevent
+\fBbill\fR
+from running the commands listed in
+\fISU\fR
+or
+\fISHELLS\fR
+since he can simply copy those commands to a different name, or use
+a shell escape from an editor or other program.
+Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
+.PP
+In general, if a user has sudo
+\fBALL\fR
+there is nothing to prevent them from creating their own program that gives
+them a root shell (or making their own copy of a shell) regardless of any
+\(oq!\&\(cq
+elements in the user specification.
+.SS "Security implications of \fIfast_glob\fR"
+If the
+\fIfast_glob\fR
+option is in use, it is not possible to reliably negate commands where the
+path name includes globbing (aka wildcard) characters.
+This is because the C library's
+fnmatch(3)
+function cannot resolve relative paths.
+While this is typically only an inconvenience for rules that grant privileges,
+it can result in a security issue for rules that subtract or revoke privileges.
+.PP
+For example, given the following
+\fIsudoers\fR
+file entry:
+.nf
+.sp
+.RS 0n
+john ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\e
+ /usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
+.RE
+.fi
+.PP
+User
+\fBjohn\fR
+can still run
+\fR/usr/bin/passwd root\fR
+if
+\fIfast_glob\fR
+is enabled by changing to
+\fI/usr/bin\fR
+and running
+\fR./passwd root\fR
+instead.
+.SS "Preventing shell escapes"
+Once
+\fBsudo\fR
+executes a program, that program is free to do whatever
+it pleases, including run other programs.
+This can be a security issue since it is not uncommon for a program to
+allow shell escapes, which lets a user bypass
+\fBsudo\fR's
+access control and logging.
+Common programs that permit shell escapes include shells (obviously),
+editors, paginators, mail and terminal programs.
+.PP
+There are two basic approaches to this problem:
+.TP 10n
+restrict
+Avoid giving users access to commands that allow the user to run
+arbitrary commands.
+Many editors have a restricted mode where shell
+escapes are disabled, though
+\fBsudoedit\fR
+is a better solution to
+running editors via
+\fBsudo\fR.
+Due to the large number of programs that
+offer shell escapes, restricting users to the set of programs that
+do not is often unworkable.
+.TP 10n
+noexec
+Many systems that support shared libraries have the ability to
+override default library functions by pointing an environment
+variable (usually
+\fRLD_PRELOAD\fR)
+to an alternate shared library.
+On such systems,
+\fBsudo\fR's
+\fInoexec\fR
+functionality can be used to prevent a program run by
+\fBsudo\fR
+from executing any other programs.
+Note, however, that this applies only to dynamically-linked
+executables.
+Statically-linked executables and executables
+running under binary emulation are not affected.
+.sp
+The
+\fInoexec\fR
+feature is known to work on SunOS, Solaris, *BSD,
+Linux, IRIX, Tru64 UNIX, macOS, HP-UX 11.x and AIX 5.3 and above.
+It should be supported on most operating systems that support the
+\fRLD_PRELOAD\fR
+environment variable.
+Check your operating system's manual pages for the dynamic linker
+(usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to see if
+\fRLD_PRELOAD\fR
+is supported.
+.sp
+On Solaris 10 and higher,
+\fInoexec\fR
+uses Solaris privileges instead of the
+\fRLD_PRELOAD\fR
+environment variable.
+.sp
+To enable
+\fInoexec\fR
+for a command, use the
+\fRNOEXEC\fR
+tag as documented
+in the User Specification section above.
+Here is that example again:
+.nf
+.sp
+.RS 10n
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.RE
+.fi
+.RS 10n
+.sp
+This allows user
+\fBaaron\fR
+to run
+\fI/usr/bin/more\fR
+and
+\fI/usr/bin/vi\fR
+with
+\fInoexec\fR
+enabled.
+This will prevent those two commands from
+executing other commands (such as a shell).
+If you are unsure whether or not your system is capable of supporting
+\fInoexec\fR
+you can always just try it out and check whether shell escapes work when
+\fInoexec\fR
+is enabled.
+.RE
+.PP
+Note that restricting shell escapes is not a panacea.
+Programs running as root are still capable of many potentially hazardous
+operations (such as changing or overwriting files) that could lead
+to unintended privilege escalation.
+In the specific case of an editor, a safer approach is to give the
+user permission to run
+\fBsudoedit\fR
+(see below).
+.SS "Secure editing"
+The
+\fBsudoers\fR
+plugin includes
+\fBsudoedit\fR
+support which allows users to securely edit files with the editor
+of their choice.
+As
+\fBsudoedit\fR
+is a built-in command, it must be specified in the
+\fIsudoers\fR
+file without a leading path.
+However, it may take command line arguments just as a normal command does.
+Wildcards used in
+\fIsudoedit\fR
+command line arguments are expected to be path names, so a forward slash
+(\(oq/\(cq)
+will not be matched by a wildcard.
+.PP
+Unlike other
+\fBsudo\fR
+commands, the editor is run with the permissions of the invoking
+user and with the environment unmodified.
+More information may be found in the description of the
+\fB\-e\fR
+option in
+sudo(@mansectsu@).
+.PP
+For example, to allow user operator to edit the
+\(lqmessage of the day\(rq
+file:
+.nf
+.sp
+.RS 6n
+operator sudoedit /etc/motd
+.RE
+.fi
+.PP
+The operator user then runs
+\fBsudoedit\fR
+as follows:
+.nf
+.sp
+.RS 6n
+$ sudoedit /etc/motd
+.RE
+.fi
+.PP
+The editor will run as the operator user, not root, on a temporary copy of
+\fI/etc/motd\fR.
+After the file has been edited,
+\fI/etc/motd\fR
+will be updated with the contents of the temporary copy.
+.PP
+Users should
+\fInever\fR
+be granted
+\fBsudoedit\fR
+permission to edit a file that resides in a directory the user
+has write access to, either directly or via a wildcard.
+If the user has write access to the directory it is possible to
+replace the legitimate file with a link to another file,
+allowing the editing of arbitrary files.
+To prevent this, starting with version 1.8.16, symbolic links will
+not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory
+unless the
+\fIsudoedit_checkdir\fR
+option has been disabled or the invoking user is root.
+Additionally, in version 1.8.15 and higher,
+\fBsudoedit\fR
+will refuse to open a symbolic link unless either the
+\fIsudoedit_follow\fR
+option is enabled or the
+\fIsudoedit\fR
+command is prefixed with the
+\fRFOLLOW\fR
+tag in the
+\fIsudoers\fR
+file.
+.SS "Time stamp file checks"
+\fBsudoers\fR
+will check the ownership of its time stamp directory
+(\fI@rundir@/ts\fR
+by default)
+and ignore the directory's contents if it is not owned by root or
+if it is writable by a user other than root.
+Older versions of
+\fBsudo\fR
+stored time stamp files in
+\fI/tmp\fR;
+this is no longer recommended as it may be possible for a user
+to create the time stamp themselves on systems that allow
+unprivileged users to change the ownership of files they create.
+.PP
+While the time stamp directory
+\fIshould\fR
+be cleared at reboot time, not all systems contain a
+\fI/run\fR
+or
+\fI/var/run\fR
+directory.
+To avoid potential problems,
+\fBsudoers\fR
+will ignore time stamp files that date from before the machine booted
+on systems where the boot time is available.
+.PP
+Some systems with graphical desktop environments allow unprivileged
+users to change the system clock.
+Since
+\fBsudoers\fR
+relies on the system clock for time stamp validation, it may be
+possible on such systems for a user to run
+\fBsudo\fR
+for longer than
+\fItimestamp_timeout\fR
+by setting the clock back.
+To combat this,
+\fBsudoers\fR
+uses a monotonic clock (which never moves backwards) for its time stamps
+if the system supports it.
+.PP
+\fBsudoers\fR
+will not honor time stamps set far in the future.
+Time stamps with a date greater than current_time + 2 *
+\fRTIMEOUT\fR
+will be ignored and
+\fBsudoers\fR
+will log and complain.
+.PP
+If the
+\fItimestamp_type\fR
+option is set to
+\(lqtty\(rq,
+the time stamp record includes the device number of the terminal
+the user authenticated with.
+This provides per-terminal granularity but time stamp records may still
+outlive the user's session.
+.PP
+Unless the
+\fItimestamp_type\fR
+option is set to
+\(lqglobal\(rq,
+the time stamp record also includes the session ID of the process
+that last authenticated.
+This prevents processes in different terminal sessions from using
+the same time stamp record.
+On systems where a process's start time can be queried,
+the start time of the session leader
+is recorded in the time stamp record.
+If no terminal is present or the
+\fItimestamp_type\fR
+option is set to
+\(lqppid\(rq,
+the start time of the parent process is used instead.
+In most cases this will prevent a time stamp record from being re-used
+without the user entering a password when logging out and back in again.
+.SH "DEBUGGING"
+Versions 1.8.4 and higher of the
+\fBsudoers\fR
+plugin support a flexible debugging framework that can help track
+down what the plugin is doing internally if there is a problem.
+This can be configured in the
+sudo.conf(@mansectform@)
+file.
+.PP
+The
+\fBsudoers\fR
+plugin uses the same debug flag format as the
+\fBsudo\fR
+front-end:
+\fIsubsystem\fR@\fIpriority\fR.
+.PP
+The priorities used by
+\fBsudoers\fR,
+in order of decreasing severity,
+are:
+\fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, \fIinfo\fR, \fItrace\fR
+and
+\fIdebug\fR.
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+\fInotice\fR
+would include debug messages logged at
+\fInotice\fR
+and higher.
+.PP
+The following subsystems are used by the
+\fBsudoers\fR
+plugin:
+.TP 10n
+\fIalias\fR
+\fRUser_Alias\fR,
+\fRRunas_Alias\fR,
+\fRHost_Alias\fR
+and
+\fRCmnd_Alias\fR
+processing
+.TP 10n
+\fIall\fR
+matches every subsystem
+.TP 10n
+\fIaudit\fR
+BSM and Linux audit code
+.TP 10n
+\fIauth\fR
+user authentication
+.TP 10n
+\fIdefaults\fR
+\fIsudoers\fR
+file
+\fIDefaults\fR
+settings
+.TP 10n
+\fIenv\fR
+environment handling
+.TP 10n
+\fIldap\fR
+LDAP-based sudoers
+.TP 10n
+\fIlogging\fR
+logging support
+.TP 10n
+\fImatch\fR
+matching of users, groups, hosts and netgroups in the
+\fIsudoers\fR
+file
+.TP 10n
+\fInetif\fR
+network interface handling
+.TP 10n
+\fInss\fR
+network service switch handling in
+\fBsudoers\fR
+.TP 10n
+\fIparser\fR
+\fIsudoers\fR
+file parsing
+.TP 10n
+\fIperms\fR
+permission setting
+.TP 10n
+\fIplugin\fR
+The equivalent of
+\fImain\fR
+for the plugin.
+.TP 10n
+\fIpty\fR
+pseudo-terminal related code
+.TP 10n
+\fIrbtree\fR
+redblack tree internals
+.TP 10n
+\fIsssd\fR
+SSSD-based sudoers
+.TP 10n
+\fIutil\fR
+utility functions
+.PD 0
+.PP
+For example:
+.nf
+.sp
+.RS 0n
+Debug sudo /var/log/sudo_debug match@info,nss@info
+.RE
+.fi
+.PD
+.PP
+For more information, see the
+sudo.conf(@mansectform@)
+manual.
+.SH "SEE ALSO"
+ssh(1),
+su(1),
+fnmatch(3),
+glob(3),
+mktemp(3),
+strftime(3),
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers.ldap(@mansectform@),
+sudoers_timestamp(@mansectform@),
+sudo(@mansectsu@),
+visudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+The
+\fIsudoers\fR
+file should
+\fBalways\fR
+be edited by the
+\fBvisudo\fR
+utility which locks the file and checks for syntax errors.
+If
+\fIsudoers\fR
+contains syntax errors,
+\fBsudo\fR
+may refuse to run, which is a serious problem if
+\fBsudo\fR
+is your only method of obtaining superuser privileges.
+Recent versions of
+\fBsudoers\fR
+will attempt to recover after a syntax error by ignoring the rest of
+the line after encountering an error.
+Older versions of
+\fBsudo\fR
+will not run if
+\fIsudoers\fR
+contains a syntax error.
+.PP
+When using netgroups of machines (as opposed to users), if you
+store fully qualified host name in the netgroup (as is usually the
+case), you either need to have the machine's host name be fully qualified
+as returned by the
+\fRhostname\fR
+command or use the
+\fIfqdn\fR
+option in
+\fIsudoers\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers.man.in.sed b/doc/sudoers.man.in.sed
new file mode 100644
index 0000000..eca83a3
--- /dev/null
+++ b/doc/sudoers.man.in.sed
@@ -0,0 +1,150 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+.nr BA @BAMAN@\
+.nr LC @LCMAN@\
+.nr PS @PSMAN@\
+\1/
+
+/^On$/N
+/^On\nBSD$/,/^.*\.$/ {
+ /^On\nBSD$/i\
+.if \\n(LC \\{\\
+ /\.$/a\
+.\\}
+}
+
+/^\.SS "SELinux_Spec"$/,/^\.SS/ {
+ /^\.SS / {
+ /^\.SS "SELinux_Spec"$/i\
+.if \\n(SL \\{\\
+ /^\.SS "SELinux_Spec"$/!i\
+.\\}
+ }
+}
+
+/^\.SS "Solaris_Priv_Spec"$/,/^\.SS/ {
+ /^\.SS / {
+ /^\.SS "Solaris_Priv_Spec"$/i\
+.if \\n(PS \\{\\
+ /^\.SS "Solaris_Priv_Spec"$/!i\
+.\\}
+ }
+}
+
+/^Option_Spec ::= / {
+ s/^.*$/.ie \\n(SL \\{\\\
+.ie \\n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec)\
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec)\
+.\\}\
+.el \\{\\\
+.ie \\n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec)\
+.el Option_Spec ::= (Date_Spec | Timeout_Spec)\
+.\\}/
+}
+
+/^SELinux_Spec ::=/ {
+ i\
+.if \\n(SL \\{\\
+ N
+ a\
+.\\}
+}
+
+/^Solaris_Priv_Spec ::=/ {
+ i\
+.if \\n(PS \\{\\
+ N
+ a\
+.\\}
+}
+
+/^SELinux roles.*types,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
+
+/^Solaris privileges sets,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+
+/^\.TP 18n$/ {
+ N
+ /^\.TP 18n\nuse_loginclass$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nuse_loginclass$/i\
+.if \\n(BA \\{\\
+ /^\.TP 18n\nuse_loginclass$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nlimitprivs$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nlimitprivs$/i\
+.if \\n(PS \\{\\
+ /^\.TP 18n\nlimitprivs$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nprivs$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nprivs$/i\
+.if \\n(PS \\{\\
+ /^\.TP 18n\nprivs$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nselinux$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nselinux$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\nselinux$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nrole$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nrole$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\nrole$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\ntype$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\ntype$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\ntype$/!i\
+.\\}
+ }
+ }
+}
+
+/^\\fRPRIVS\\fR,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+/^\\fRLIMITPRIVS\\fR,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+
+/^\\fRROLE\\fR,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
+/^\\fRTYPE\\fR,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in
new file mode 100644
index 0000000..c14855b
--- /dev/null
+++ b/doc/sudoers.mdoc.in
@@ -0,0 +1,6051 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2021
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.Dd January 8, 2020
+.Dt SUDOERS @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers
+.Nd default sudo security policy plugin
+.Sh DESCRIPTION
+The
+.Nm
+policy plugin determines a user's
+.Nm sudo
+privileges.
+It is the default
+.Nm sudo
+policy plugin.
+The policy is driven by
+the
+.Pa @sysconfdir@/sudoers
+file or, optionally in LDAP.
+The policy format is described in detail in the
+.Sx SUDOERS FILE FORMAT
+section.
+For information on storing
+.Nm
+policy information
+in LDAP, please see
+.Xr sudoers.ldap @mansectform@ .
+.Ss Configuring sudo.conf for sudoers
+.Nm sudo
+consults the
+.Xr sudo.conf @mansectform@
+file to determine which policy and I/O logging plugins to load.
+If no
+.Xr sudo.conf @mansectform@
+file is present, or if it contains no
+.Li Plugin
+lines,
+.Nm
+will be used for policy decisions and I/O logging.
+To explicitly configure
+.Xr sudo.conf @mansectform@
+to use the
+.Nm
+plugin, the following configuration can be used.
+.Bd -literal -offset indent
+Plugin sudoers_audit sudoers.so
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+.Ed
+.Pp
+Starting with
+.Nm sudo
+1.8.5, it is possible to specify optional arguments to the
+.Nm
+plugin in the
+.Xr sudo.conf @mansectform@
+file.
+Plugin arguments, if any, should be listed after the path to the plugin
+(i.e., after
+.Pa sudoers.so ) .
+The arguments are only effective for the plugin that opens (and parses) the
+.Em sudoers
+file.
+.Pp
+For
+.Nm sudo
+version 1.9.1 and higher, this is the
+.Em sudoers_audit
+plugin.
+For older versions, it is the
+.Em sudoers_policy
+plugin.
+Multiple arguments may be specified, separated by white space.
+For example:
+.Bd -literal -offset indent
+Plugin sudoers_audit sudoers.so sudoers_mode=0400 error_recovery=false
+.Ed
+.Pp
+The following plugin arguments are supported:
+.Bl -tag -width 8n
+.It error_recovery=bool
+The
+.Em error_recovery
+argument can be used to control whether
+.Nm
+should attempt to recover from syntax errors in the
+.Em sudoers
+file.
+If set to
+.Em true
+(the default),
+.Nm
+will try to recover from a syntax error by discarding the portion
+of the line that contains the error until the end of the line.
+A value of
+.Em false
+will disable error recovery.
+Prior to version 1.9.3, no error recovery was performed.
+.It ldap_conf=pathname
+The
+.Em ldap_conf
+argument can be used to override the default path to the
+.Pa ldap.conf
+file.
+.It ldap_secret=pathname
+The
+.Em ldap_secret
+argument can be used to override the default path to the
+.Pa ldap.secret
+file.
+.It sudoers_file=pathname
+The
+.Em sudoers_file
+argument can be used to override the default path to the
+.Em sudoers
+file.
+.It sudoers_uid=uid
+The
+.Em sudoers_uid
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.It sudoers_gid=gid
+The
+.Em sudoers_gid
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.It sudoers_mode=mode
+The
+.Em sudoers_mode
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.El
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+please refer to its manual.
+.Ss User Authentication
+The
+.Nm
+security policy requires that most users authenticate
+themselves before they can use
+.Nm sudo .
+A password is not required
+if the invoking user is root, if the target user is the same as the
+invoking user, or if the policy has disabled authentication for the
+user or command.
+Unlike
+.Xr su 1 ,
+when
+.Nm
+requires
+authentication, it validates the invoking user's credentials, not
+the target user's (or root's) credentials.
+This can be changed via
+the
+.Em rootpw ,
+.Em targetpw
+and
+.Em runaspw
+flags, described later.
+.Pp
+If a user who is not listed in the policy tries to run a command
+via
+.Nm sudo ,
+mail is sent to the proper authorities.
+The address
+used for such mail is configurable via the
+.Em mailto
+Defaults entry
+(described later) and defaults to
+.Li @mailto@ .
+.Pp
+Note that no mail will be sent if an unauthorized user tries to run
+.Nm sudo
+with the
+.Fl l
+or
+.Fl v
+option unless there is an authentication error and
+either the
+.Em mail_always
+or
+.Em mail_badpass
+flags are enabled.
+This allows users to
+determine for themselves whether or not they are allowed to use
+.Nm sudo .
+By default, all attempts to run
+.Nm sudo
+(successful or not)
+are logged, regardless of whether or not mail is sent.
+.Pp
+If
+.Nm sudo
+is run by root and the
+.Ev SUDO_USER
+environment variable
+is set, the
+.Nm
+policy will use this value to determine who
+the actual user is.
+This can be used by a user to log commands
+through sudo even when a root shell has been invoked.
+It also
+allows the
+.Fl e
+option to remain useful even when invoked via a
+sudo-run script or program.
+Note, however, that the
+.Em sudoers
+file lookup is still done for root, not the user specified by
+.Ev SUDO_USER .
+.Pp
+.Nm
+uses per-user time stamp files for credential caching.
+Once a user has been authenticated, a record is written
+containing the user-ID that was used to authenticate, the
+terminal session ID, the start time of the session leader
+(or parent process) and a time stamp
+(using a monotonic clock if one is available).
+The user may then use
+.Nm sudo
+without a password for a short period of time
+.Po
+.Li @timeout@
+minutes unless overridden by the
+.Em timestamp_timeout
+option
+.Pc .
+By default,
+.Nm
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+.Em timestamp_type
+option can be used to select the type of time stamp record
+.Nm
+will use.
+.Ss Logging
+By default,
+.Nm
+logs both successful and unsuccessful attempts (as well
+as errors).
+The
+.Em log_allowed
+and
+.Em log_denied
+flags can be used to control this behavior.
+Messages can be logged to
+.Xr syslog 3 ,
+a log file, or both.
+The default is to log to
+.Xr syslog 3
+but this is configurable via the
+.Em syslog
+and
+.Em logfile
+settings.
+See
+.Sx "LOG FORMAT"
+for a description of the log file format.
+.Pp
+.Nm
+is also capable of running a command in a pseudo-terminal and logging all
+input and/or output.
+The standard input, standard output and standard error can be logged
+even when not associated with a terminal.
+I/O logging is not on by default but can be enabled using
+the
+.Em log_input
+and
+.Em log_output
+options as well as the
+.Li LOG_INPUT
+and
+.Li LOG_OUTPUT
+command tags.
+See
+.Sx "I/O LOG FILES"
+for details on how I/O log files are stored.
+.Pp
+Starting with version 1.9, the
+.Em log_servers
+setting may be used to send event and I/O log data to a remote server running
+.Nm sudo_logsrvd
+or another service that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Ss Command environment
+Since environment variables can influence program behavior,
+.Nm
+provides a means to restrict which variables from the user's
+environment are inherited by the command to be run.
+There are two
+distinct ways
+.Nm
+can deal with environment variables.
+.Pp
+By default, the
+.Em env_reset
+flag is enabled.
+This causes commands
+to be executed with a new, minimal environment.
+On AIX (and Linux
+systems without PAM), the environment is initialized with the
+contents of the
+.Pa /etc/environment
+file.
+.if \n(LC \{\
+On
+.Bx
+systems, if the
+.Em use_loginclass
+flag is enabled, the environment is initialized
+based on the
+.Em path
+and
+.Em setenv
+settings in
+.Pa /etc/login.conf .
+.\}
+The
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev LOGNAME
+and
+.Ev USER
+environment variables are initialized based on the target user
+and the
+.Ev SUDO_*
+variables are set based on the invoking user.
+Additional variables, such as
+.Ev DISPLAY ,
+.Ev PATH
+and
+.Ev TERM ,
+are preserved from the invoking user's environment if permitted by the
+.Em env_check
+or
+.Em env_keep
+options.
+A few environment variables are treated specially.
+If the
+.Ev PATH
+and
+.Ev TERM
+variables are not preserved from the user's environment, they will be set
+to default values.
+The
+.Ev LOGNAME
+and
+.Ev USER
+are handled as a single entity.
+If one of them is preserved (or removed) from the user's environment,
+the other will be as well.
+If
+.Ev LOGNAME
+and
+.Ev USER
+are to be preserved but only one of them is present in the user's environment,
+the other will be set to the same value.
+This avoids an inconsistent environment where one of the variables
+describing the user name is set to the invoking user and one is
+set to the target user.
+Environment variables with a value beginning with
+.Li ()
+are removed unless both the name and value parts are matched by
+.Em env_keep
+or
+.Em env_check ,
+as they may be interpreted as functions by the
+.Sy bash
+shell.
+Prior to version 1.8.11, such variables were always removed.
+.Pp
+If, however, the
+.Em env_reset
+flag is disabled, any variables not
+explicitly denied by the
+.Em env_check
+and
+.Em env_delete
+options are allowed and their values are
+inherited from the invoking process.
+Prior to version 1.8.21, environment variables with a value beginning with
+.Li ()
+were always removed.
+Beginning with version 1.8.21, a pattern in
+.Em env_delete
+is used to match
+.Sy bash
+shell functions instead.
+Since it is not possible
+to block all potentially dangerous environment variables, use
+of the default
+.Em env_reset
+behavior is encouraged.
+.Pp
+Environment variables specified by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep
+may include one or more
+.Ql *
+characters which will match zero or more characters.
+No other wildcard characters are supported.
+.Pp
+By default, environment variables are matched by name.
+However, if the pattern includes an equal sign
+.Pq Ql =\& ,
+both the variables name and value must match.
+For example, a
+.Sy bash
+shell function could be matched as follows:
+.Bd -literal -offset 4n
+env_keep += "BASH_FUNC_my_func%%=()*"
+.Ed
+.Pp
+Without the
+.Dq Li =()*
+suffix, this would not match, as
+.Sy bash
+shell functions are not preserved by default.
+.Pp
+The complete list of environment variables that are preserved or removed,
+as modified by global Defaults parameters in
+.Em sudoers ,
+is displayed when
+.Nm sudo
+is run by root with the
+.Fl V
+option.
+Please note that the list of environment variables to remove
+varies based on the operating system
+.Nm sudo
+is running on.
+.Pp
+Other
+.Nm
+options may influence the command environment, such as
+.Em always_set_home ,
+.Em secure_path ,
+.Em set_logname ,
+and
+.Em set_home .
+.Pp
+On systems that support PAM where the
+.Sy pam_env
+module is enabled for
+.Nm sudo ,
+variables in the PAM environment may be merged in to the environment.
+If a variable in the PAM environment is already present in the
+user's environment, the value will only be overridden if the variable
+was not preserved by
+.Nm .
+When
+.Em env_reset
+is enabled, variables preserved from the invoking user's environment
+by the
+.Em env_keep
+list take precedence over those in the PAM environment.
+When
+.Em env_reset
+is disabled, variables present the invoking user's environment
+take precedence over those in the PAM environment unless they
+match a pattern in the
+.Em env_delete
+list.
+.Pp
+Note that the dynamic linker on most operating systems will remove
+variables that can control dynamic linking from the environment of
+set-user-ID executables, including
+.Nm sudo .
+Depending on the operating
+system this may include
+.Ev _RLD* ,
+.Ev DYLD_* ,
+.Ev LD_* ,
+.Ev LDR_* ,
+.Ev LIBPATH ,
+.Ev SHLIB_PATH ,
+and others.
+These type of variables are
+removed from the environment before
+.Nm sudo
+even begins execution
+and, as such, it is not possible for
+.Nm sudo
+to preserve them.
+.Pp
+As a special case, if the
+.Fl i
+option (initial login) is
+specified,
+.Nm
+will initialize the environment regardless
+of the value of
+.Em env_reset .
+The
+.Ev DISPLAY ,
+.Ev PATH
+and
+.Ev TERM
+variables remain unchanged;
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev USER ,
+and
+.Ev LOGNAME
+are set based on the target user.
+On AIX (and Linux
+systems without PAM), the contents of
+.Pa /etc/environment
+are also
+included.
+.if \n(LC \{\
+On
+.Bx
+systems, if the
+.Em use_loginclass
+flag is
+enabled, the
+.Em path
+and
+.Em setenv
+variables in
+.Pa /etc/login.conf
+are also applied.
+.\}
+All other environment variables are removed unless permitted by
+.Em env_keep
+or
+.Em env_check ,
+described above.
+.Pp
+Finally, the
+.Em restricted_env_file
+and
+.Em env_file
+files are applied, if present.
+The variables in
+.Em restricted_env_file
+are applied first and are subject to the same restrictions as the
+invoking user's environment, as detailed above.
+The variables in
+.Em env_file
+are applied last and are not subject to these restrictions.
+In both cases, variables present in the files will only be set to
+their specified values if they would not conflict with an existing
+environment variable.
+.Sh SUDOERS FILE FORMAT
+The
+.Em sudoers
+file is composed of two types of entries: aliases
+(basically variables) and user specifications (which specify who
+may run what).
+.Pp
+When multiple entries match for a user, they are applied in order.
+Where there are multiple matches, the last match is used (which is
+not necessarily the most specific match).
+.Pp
+The
+.Em sudoers
+file grammar will be described below in Extended Backus-Naur
+Form (EBNF).
+Don't despair if you are unfamiliar with EBNF; it is fairly simple,
+and the definitions below are annotated.
+.Ss Quick guide to EBNF
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of
+.Em production rules .
+E.g.,
+.Pp
+.Li symbol ::= definition | alternate1 | alternate2 ...
+.Pp
+Each
+.Em production rule
+references others and thus makes up a
+grammar for the language.
+EBNF also contains the following
+operators, which many readers will recognize from regular
+expressions.
+Do not, however, confuse them with
+.Dq wildcard
+characters, which have different meanings.
+.Bl -tag -width 4n
+.It Li \&?
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
+.It Li *
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
+.It Li +
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
+.El
+.Pp
+Parentheses may be used to group symbols together.
+For clarity,
+we will use single quotes
+.Pq ''
+to designate what is a verbatim character string (as opposed to a symbol name).
+.Ss Aliases
+There are four kinds of aliases:
+.Li User_Alias ,
+.Li Runas_Alias ,
+.Li Host_Alias
+and
+.Li Cmnd_Alias .
+Beginning with
+.Nm sudo
+1.9.0,
+.Li Cmd_Alias
+may be used in place of
+.Li Cmnd_Alias
+if desired.
+.Bd -literal
+Alias ::= 'User_Alias' User_Alias_Spec (':' User_Alias_Spec)* |
+ 'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
+ 'Host_Alias' Host_Alias_Spec (':' Host_Alias_Spec)* |
+ 'Cmnd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
+ 'Cmd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
+
+User_Alias ::= NAME
+
+User_Alias_Spec ::= User_Alias '=' User_List
+
+Runas_Alias ::= NAME
+
+Runas_Alias_Spec ::= Runas_Alias '=' Runas_List
+
+Host_Alias ::= NAME
+
+Host_Alias_Spec ::= Host_Alias '=' Host_List
+
+Cmnd_Alias ::= NAME
+
+Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
+
+NAME ::= [A-Z]([A-Z][0-9]_)*
+.Ed
+.Pp
+Each
+.Em alias
+definition is of the form
+.Bd -literal
+Alias_Type NAME = item1, item2, ...
+.Ed
+.Pp
+where
+.Em Alias_Type
+is one of
+.Li User_Alias ,
+.Li Runas_Alias ,
+.Li Host_Alias ,
+or
+.Li Cmnd_Alias .
+A
+.Li NAME
+is a string of uppercase letters, numbers,
+and underscore characters
+.Pq Ql _ .
+A
+.Li NAME
+.Sy must
+start with an
+uppercase letter.
+It is possible to put several alias definitions
+of the same type on a single line, joined by a colon
+.Pq Ql :\& .
+E.g.,
+.Bd -literal
+Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+.Ed
+.Pp
+It is a syntax error to redefine an existing
+.Em alias .
+It is possible to use the same name for
+.Em aliases
+of different types, but this is not recommended.
+.Pp
+The definitions of what constitutes a valid
+.Em alias
+member follow.
+.Bd -literal
+User_List ::= User |
+ User ',' User_List
+
+User ::= '!'* user name |
+ '!'* #uid |
+ '!'* %group |
+ '!'* %#gid |
+ '!'* +netgroup |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* User_Alias
+.Ed
+.Pp
+A
+.Li User_List
+is made up of one or more user names, user-IDs
+(prefixed with
+.Ql # ) ,
+system group names and IDs (prefixed with
+.Ql %
+and
+.Ql %#
+respectively), netgroups (prefixed with
+.Ql + ) ,
+non-Unix group names and IDs (prefixed with
+.Ql %:
+and
+.Ql %:#
+respectively) and
+.Li User_Alias Ns es.
+Each list item may be prefixed with zero or more
+.Ql \&!
+operators.
+An odd number of
+.Ql \&!
+operators negate the value of
+the item; an even number just cancel each other out.
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+.Pp
+A
+.Li user name ,
+.Li uid ,
+.Li group ,
+.Li gid ,
+.Li netgroup ,
+.Li nonunix_group
+or
+.Li nonunix_gid
+may be enclosed in double quotes to avoid the
+need for escaping special characters.
+Alternately, special characters
+may be specified in escaped hex mode, e.g., \ex20 for space.
+When
+using double quotes, any prefix characters must be included inside
+the quotes.
+.Pp
+The actual
+.Li nonunix_group
+and
+.Li nonunix_gid
+syntax depends on
+the underlying group provider plugin.
+For instance, the QAS AD plugin supports the following formats:
+.Bl -bullet -width 1n
+.It
+Group in the same domain: "%:Group Name"
+.It
+Group in any domain: "%:Group Name@FULLY.QUALIFIED.DOMAIN"
+.It
+Group SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
+.El
+.Pp
+See
+.Sx "GROUP PROVIDER PLUGINS"
+for more information.
+.Pp
+Note that quotes around group names are optional.
+Unquoted strings must use a backslash
+.Pq Ql \e
+to escape spaces and special characters.
+See
+.Sx Other special characters and reserved words
+for a list of
+characters that need to be escaped.
+.Bd -literal
+Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
+
+Runas_Member ::= '!'* user name |
+ '!'* #uid |
+ '!'* %group |
+ '!'* %#gid |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* +netgroup |
+ '!'* Runas_Alias
+.Ed
+.Pp
+A
+.Li Runas_List
+is similar to a
+.Li User_List
+except that instead
+of
+.Li User_Alias Ns es
+it can contain
+.Li Runas_Alias Ns es .
+Note that
+user names and groups are matched as strings.
+In other words, two users (groups) with the same user (group) ID
+are considered to be distinct.
+If you wish to match all user names with the same user-ID (e.g., root and
+toor), you can use a user-ID instead of a name (#0 in the example given).
+Note that the user-ID or group-ID specified in a
+.Li Runas_Member
+need not be listed in the password or group database.
+.Bd -literal
+Host_List ::= Host |
+ Host ',' Host_List
+
+Host ::= '!'* host name |
+ '!'* ip_addr |
+ '!'* network(/netmask)? |
+ '!'* +netgroup |
+ '!'* Host_Alias
+.Ed
+.Pp
+A
+.Li Host_List
+is made up of one or more host names, IP addresses,
+network numbers, netgroups (prefixed with
+.Ql + )
+and other aliases.
+Again, the value of an item may be negated with the
+.Ql \&!
+operator.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If you specify a network number without a netmask,
+.Nm sudo
+will query each of the local host's network interfaces and,
+if the network number corresponds to one of the hosts's network
+interfaces, will use the netmask of that interface.
+The netmask may be specified either in standard IP address notation
+(e.g., 255.255.255.0 or ffff:ffff:ffff:ffff::),
+or CIDR notation (number of bits, e.g., 24 or 64).
+A host name may include shell-style wildcards (see the
+.Sx Wildcards
+section below),
+but unless the
+.Li host name
+command on your machine returns the fully
+qualified host name, you'll need to use the
+.Em fqdn
+flag for wildcards to be useful.
+Note that
+.Nm sudo
+only inspects actual network interfaces; this means that IP address
+127.0.0.1 (localhost) will never match.
+Also, the host name
+.Dq localhost
+will only match if that is the actual host name, which is usually
+only the case for non-networked systems.
+.Bd -literal
+digest ::= [A-Fa-f0-9]+ |
+ [A-Za-z0-9\e+/=]+
+
+Digest_Spec ::= "sha224" ':' digest |
+ "sha256" ':' digest |
+ "sha384" ':' digest |
+ "sha512" ':' digest
+
+Digest_List ::= Digest_Spec |
+ Digest_Spec ',' Digest_List
+
+Cmnd_List ::= Cmnd |
+ Cmnd ',' Cmnd_List
+
+command name ::= file name |
+ file name args |
+ file name '""'
+
+Edit_Spec ::= "sudoedit" file name+
+
+Cmnd ::= Digest_List? '!'* command name |
+ '!'* directory |
+ '!'* Edit_Spec |
+ '!'* Cmnd_Alias
+.Ed
+.Pp
+A
+.Li Cmnd_List
+is a list of one or more command names, directories, and other aliases.
+A command name is a fully qualified file name which may include
+shell-style wildcards (see the
+.Sx Wildcards
+section below).
+A simple file name allows the user to run the command with any
+arguments they wish.
+However, you may also specify command line arguments (including
+wildcards).
+Alternately, you can specify
+.Li \&""
+to indicate that the command
+may only be run
+.Sy without
+command line arguments.
+A directory is a
+fully qualified path name ending in a
+.Ql / .
+When you specify a directory in a
+.Li Cmnd_List ,
+the user will be able to run any file within that directory
+(but not in any sub-directories therein).
+.Pp
+If a
+.Li Cmnd
+has associated command line arguments, then the arguments
+in the
+.Li Cmnd
+must match exactly those given by the user on the command line
+(or match the wildcards if there are any).
+Note that the following characters must be escaped with a
+.Ql \e
+if they are used in command arguments:
+.Ql ,\& ,
+.Ql :\& ,
+.Ql =\& ,
+.Ql \e .
+The built-in command
+.Dq Li sudoedit
+is used to permit a user to run
+.Nm sudo
+with the
+.Fl e
+option (or as
+.Nm sudoedit ) .
+It may take command line arguments just as a normal command does.
+Note that
+.Dq Li sudoedit
+is a command built into
+.Nm sudo
+itself and must be specified in the
+.Em sudoers
+file
+.Sy without
+a leading path.
+If a leading path is present, for example
+.Pa /usr/bin/sudoedit ,
+the path name will be silently converted to
+.Dq Li sudoedit .
+A fully-qualified path for
+.Nm sudoedit
+is treated as an error by
+.Nm visudo .
+.Pp
+A
+.Li command name
+may be preceded by a
+.Li Digest_List ,
+a comma-separated list of one or more
+.Li Digest_Spec
+entries.
+If a
+.Li Digest_List
+is present, the command will only match successfully if it can be verified
+using one of the SHA-2 digests in the list.
+Starting with version 1.9.0, the
+.Sy ALL
+reserved word can be used in conjunction with a
+.Li Digest_List .
+The following digest formats are supported: sha224, sha256, sha384 and sha512.
+The string may be specified in either hex or base64 format
+(base64 is more compact).
+There are several utilities capable of generating SHA-2 digests in hex
+format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
+.Pp
+For example, using openssl:
+.Bd -literal
+$ openssl dgst -sha224 /bin/ls
+SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
+.Ed
+.Pp
+It is also possible to use openssl to generate base64 output:
+.Bd -literal
+$ openssl dgst -binary -sha224 /bin/ls | openssl base64
+EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
+.Ed
+.Pp
+Warning, if the user has write access to the command itself (directly or via a
+.Nm sudo
+command), it may be possible for the user to replace the command after the
+digest check has been performed but before the command is executed.
+A similar race condition exists on systems that lack the
+.Xr fexecve 2
+system call when the directory in which the command is located
+is writable by the user.
+See the description of the
+.Em fdexec
+setting for more information on how
+.Nm sudo
+executes commands that have an associated digest.
+.Pp
+Command digests are only supported by version 1.8.7 or higher.
+.Ss Defaults
+Certain configuration options may be changed from their default
+values at run-time via one or more
+.Li Default_Entry
+lines.
+These may affect all users on any host, all users on a specific host, a
+specific user, a specific command, or commands being run as a specific user.
+Note that per-command entries may not include command line arguments.
+If you need to specify arguments, define a
+.Li Cmnd_Alias
+and reference
+that instead.
+.Bd -literal
+Default_Type ::= 'Defaults' |
+ 'Defaults' '@' Host_List |
+ 'Defaults' ':' User_List |
+ 'Defaults' '!' Cmnd_List |
+ 'Defaults' '>' Runas_List
+
+Default_Entry ::= Default_Type Parameter_List
+
+Parameter_List ::= Parameter |
+ Parameter ',' Parameter_List
+
+Parameter ::= Parameter '=' Value |
+ Parameter '+=' Value |
+ Parameter '-=' Value |
+ '!'* Parameter
+.Ed
+.Pp
+Parameters may be
+.Sy flags ,
+.Sy integer
+values,
+.Sy strings ,
+or
+.Sy lists .
+Flags are implicitly boolean and can be turned off via the
+.Ql \&!
+operator.
+Some integer, string and list parameters may also be
+used in a boolean context to disable them.
+Values may be enclosed
+in double quotes
+.Pq \&""
+when they contain multiple words.
+Special characters may be escaped with a backslash
+.Pq Ql \e .
+.Pp
+Lists have two additional assignment operators,
+.Li +=
+and
+.Li -= .
+These operators are used to add to and delete from a list respectively.
+It is not an error to use the
+.Li -=
+operator to remove an element
+that does not exist in a list.
+.Pp
+Defaults entries are parsed in the following order: generic, host,
+user and runas Defaults first, then command defaults.
+If there are multiple Defaults settings of the same type, the last
+matching setting is used.
+The following Defaults settings are parsed before all others since
+they may affect subsequent entries:
+.Em fqdn ,
+.Em group_plugin ,
+.Em runas_default ,
+.Em sudoers_locale .
+.Pp
+See
+.Sx SUDOERS OPTIONS
+for a list of supported Defaults parameters.
+.Ss User specification
+.Bd -literal
+User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e
+ (':' Host_List '=' Cmnd_Spec_List)*
+
+Cmnd_Spec_List ::= Cmnd_Spec |
+ Cmnd_Spec ',' Cmnd_Spec_List
+
+Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd
+
+Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
+
+.ie \n(SL \{\
+.ie \n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.\}
+.el \{\
+.ie \n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.el Option_Spec ::= (Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.\}
+
+.if \n(SL \{\
+SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
+
+.\}
+.if \n(PS \{\
+Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
+
+.\}
+Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
+
+Timeout_Spec ::= 'TIMEOUT=timeout'
+
+Chdir_Spec ::= 'CWD=directory'
+
+Chroot_Spec ::= 'CHROOT=directory'
+
+Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
+ 'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
+ 'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
+ 'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')
+.Ed
+.Pp
+A
+.Sy user specification
+determines which commands a user may run
+(and as what user) on specified hosts.
+By default, commands are
+run as
+.Sy root ,
+but this can be changed on a per-command basis.
+.Pp
+The basic structure of a user specification is
+.Dq who where = (as_whom) what .
+Let's break that down into its constituent parts:
+.Ss Runas_Spec
+A
+.Li Runas_Spec
+determines the user and/or the group that a command
+may be run as.
+A fully-specified
+.Li Runas_Spec
+consists of two
+.Li Runas_List Ns s
+(as defined above) separated by a colon
+.Pq Ql :\&
+and enclosed in a set of parentheses.
+The first
+.Li Runas_List
+indicates which users the command may be run as via the
+.Fl u
+option.
+The second defines a list of groups that can be specified via the
+.Fl g
+option in addition to any of the target user's groups.
+If both
+.Li Runas_List Ns s
+are specified, the command may be run with any combination of users
+and groups listed in their respective
+.Li Runas_List Ns s.
+If only the first is specified, the command may be run as any user
+in the list but no
+.Fl g
+option
+may be specified.
+If the first
+.Li Runas_List
+is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the
+.Li Runas_List .
+If both
+.Li Runas_List Ns s
+are empty, the command may only be run as the invoking user.
+If no
+.Li Runas_Spec
+is specified the command may be run as
+.Sy root
+and
+no group may be specified.
+.Pp
+A
+.Li Runas_Spec
+sets the default for the commands that follow it.
+What this means is that for the entry:
+.Bd -literal
+dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
+.Ed
+.Pp
+The user
+.Sy dgb
+may run
+.Pa /bin/ls ,
+.Pa /bin/kill ,
+and
+.Pa /usr/bin/lprm
+on the host
+.No boulder Ns \(em Ns but
+only as
+.Sy operator .
+E.g.,
+.Bd -literal
+$ sudo -u operator /bin/ls
+.Ed
+.Pp
+It is also possible to override a
+.Li Runas_Spec
+later on in an entry.
+If we modify the entry like so:
+.Bd -literal
+dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+.Ed
+.Pp
+Then user
+.Sy dgb
+is now allowed to run
+.Pa /bin/ls
+as
+.Sy operator ,
+but
+.Pa /bin/kill
+and
+.Pa /usr/bin/lprm
+as
+.Sy root .
+.Pp
+We can extend this to allow
+.Sy dgb
+to run
+.Li /bin/ls
+with either
+the user or group set to
+.Sy operator :
+.Bd -literal
+dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill,\e
+ /usr/bin/lprm
+.Ed
+.Pp
+Note that while the group portion of the
+.Li Runas_Spec
+permits the
+user to run as command with that group, it does not force the user
+to do so.
+If no group is specified on the command line, the command
+will run with the group listed in the target user's password database
+entry.
+The following would all be permitted by the sudoers entry above:
+.Bd -literal
+$ sudo -u operator /bin/ls
+$ sudo -u operator -g operator /bin/ls
+$ sudo -g operator /bin/ls
+.Ed
+.Pp
+In the following example, user
+.Sy tcm
+may run commands that access
+a modem device file with the dialer group.
+.Bd -literal
+tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu,\e
+ /usr/local/bin/minicom
+.Ed
+.Pp
+Note that in this example only the group will be set, the command
+still runs as user
+.Sy tcm .
+E.g.\&
+.Bd -literal
+$ sudo -g dialer /usr/bin/cu
+.Ed
+.Pp
+Multiple users and groups may be present in a
+.Li Runas_Spec ,
+in which case the user may select any combination of users and groups via the
+.Fl u
+and
+.Fl g
+options.
+In this example:
+.Bd -literal
+alan ALL = (root, bin : operator, system) ALL
+.Ed
+.Pp
+user
+.Sy alan
+may run any command as either user root or bin,
+optionally setting the group to operator or system.
+.Ss Option_Spec
+A
+.Li Cmnd
+may have zero or more options associated with it.
+Options may consist of
+.if \n(SL \{\
+SELinux roles and/or types,
+.\}
+.if \n(PS \{\
+Solaris privileges sets,
+.\}
+start and/or end dates and command timeouts.
+Once an option is set for a
+.Li Cmnd ,
+subsequent
+.Li Cmnd Ns s
+in the
+.Li Cmnd_Spec_List ,
+inherit that option unless it is overridden by another option.
+Note that the option names are reserved words in
+.Em sudoers .
+This means that none of the valid option names (see below) can be used
+when declaring an alias.
+.if \n(SL \{\
+.Ss SELinux_Spec
+On systems with SELinux support,
+.Em sudoers
+file entries may optionally have an SELinux role and/or type associated
+with a command.
+If a role or
+type is specified with the command it will override any default values
+specified in
+.Em sudoers .
+A role or type specified on the command line,
+however, will supersede the values in
+.Em sudoers .
+.\}
+.if \n(PS \{\
+.Ss Solaris_Priv_Spec
+On Solaris systems,
+.Em sudoers
+file entries may optionally specify Solaris privilege set and/or limit
+privilege set associated with a command.
+If privileges or limit privileges are specified with the command
+it will override any default values specified in
+.Em sudoers .
+.Pp
+A privilege set is a comma-separated list of privilege names.
+The
+.Xr ppriv 1
+command can be used to list all privileges known to the system.
+For example:
+.Bd -literal
+$ ppriv -l
+.Ed
+.Pp
+In addition, there are several
+.Dq special
+privilege strings:
+.Bl -tag -width 8n
+.It none
+the empty set
+.It all
+the set of all privileges
+.It zone
+the set of all privileges available in the current zone
+.It basic
+the default set of privileges normal users are granted at login time
+.El
+.Pp
+Privileges can be excluded from a set by prefixing the privilege
+name with either an
+.Ql \&!
+or
+.Ql \-
+character.
+.\}
+.Ss Date_Spec
+.Nm
+rules can be specified with a start and end date via the
+.Li NOTBEFORE
+and
+.Li NOTAFTER
+settings.
+The time stamp must be specified in
+.Em Generalized Time
+as defined by RFC 4517.
+The format is effectively
+.Li yyyymmddHHMMSSZ
+where the minutes and seconds are optional.
+The
+.Ql Z
+suffix indicates that the time stamp is in Coordinated Universal Time (UTC).
+It is also possible to specify a timezone offset from UTC in hours
+and minutes instead of a
+.Ql Z .
+For example,
+.Ql -0500
+would correspond to Eastern Standard time in the US.
+As an extension, if no
+.Ql Z
+or timezone offset is specified, local time will be used.
+.Pp
+The following are all valid time stamps:
+.Bd -literal -offset 4n
+20170214083000Z
+2017021408Z
+20160315220000-0500
+20151201235900
+.Ed
+.Ss Timeout_Spec
+A command may have a timeout associated with it.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The timeout may be specified in combinations of days, hours,
+minutes and seconds with a single-letter case-insensitive suffix
+that indicates the unit of time.
+For example, a timeout of 7 days, 8 hours, 30 minutes and
+10 seconds would be written as
+.Li 7d8h30m10s .
+If a number is specified without a unit, seconds are assumed.
+Any of the days, minutes, hours or seconds may be omitted.
+The order must be from largest to smallest unit and a unit
+may not be specified more than once.
+.Pp
+The following are all
+.Em valid
+timeout values:
+.Li 7d8h30m10s ,
+.Li 14d ,
+.Li 8h30m ,
+.Li 600s ,
+.Li 3600 .
+The following are
+.Em invalid
+timeout values:
+.Li 12m2w1d ,
+.Li 30s10m4h ,
+.Li 1d2d3h .
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.Ss Chdir_Spec
+The working directory that the command will be run in can be specified
+using the
+.Li CWD
+setting.
+The
+.Fa directory
+must be a fully-qualified path name beginning with a
+.Sq /
+or
+.Sq ~
+character, or the special value
+.Dq * .
+A value of
+.Dq *
+indicates that the user may specify the working directory by running
+.Nm sudo
+with the
+.Fl D
+option.
+By default, commands are run from the invoking user's current working
+directory, unless the
+.Fl i
+option is given.
+Path names of the form
+.Li ~user/path/name
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.Ss Chroot_Spec
+The root directory that the command will be run in can be specified
+using the
+.Li CHROOT
+setting.
+The
+.Fa directory
+must be a fully-qualified path name beginning with a
+.Sq /
+or
+.Sq ~
+character, or the special value
+.Dq * .
+A value of
+.Dq *
+indicates that the user may specify the root directory by running
+.Nm sudo
+with the
+.Fl R
+option.
+This setting can be used to run the command in a
+.Xr chroot 2
+.Dq sandbox
+similar to the
+.Xr chroot @mansectsu@
+utility.
+Path names of the form
+.Li ~user/path/name
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.Ss Tag_Spec
+A command may have zero or more tags associated with it.
+The following tag values are supported:
+.Li EXEC ,
+.Li NOEXEC ,
+.Li FOLLOW ,
+.Li NOFOLLOW ,
+.Li LOG_INPUT ,
+.Li NOLOG_INPUT ,
+.Li LOG_OUTPUT ,
+.Li NOLOG_OUTPUT ,
+.Li MAIL ,
+.Li NOMAIL ,
+.Li PASSWD ,
+.Li NOPASSWD ,
+.Li SETENV ,
+and
+.Li NOSETENV .
+Once a tag is set on a
+.Li Cmnd ,
+subsequent
+.Li Cmnd Ns s
+in the
+.Li Cmnd_Spec_List ,
+inherit the tag unless it is overridden by the opposite tag (in other words,
+.Li PASSWD
+overrides
+.Li NOPASSWD
+and
+.Li NOEXEC
+overrides
+.Li EXEC ) .
+.Bl -hang -width 0n
+.It Em EXEC No and Em NOEXEC
+.sp
+If
+.Nm sudo
+has been compiled with
+.Em noexec
+support and the underlying operating system supports it, the
+.Li NOEXEC
+tag can be used to prevent a dynamically-linked executable from
+running further commands itself.
+.Pp
+In the following example, user
+.Sy aaron
+may run
+.Pa /usr/bin/more
+and
+.Pa /usr/bin/vi
+but shell escapes will be disabled.
+.Bd -literal
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.Ed
+.Pp
+See the
+.Sx Preventing shell escapes
+section below for more details on how
+.Li NOEXEC
+works and whether or not it will work on your system.
+.It Em FOLLOW No and Em NOFOLLOW
+Starting with version 1.8.15,
+.Nm sudoedit
+will not open a file that is a symbolic link unless the
+.Em sudoedit_follow
+flag is enabled.
+The
+.Em FOLLOW
+and
+.Em NOFOLLOW
+tags override the value of
+.Em sudoedit_follow
+and can be used to permit (or deny) the editing of symbolic links
+on a per-command basis.
+These tags are only effective for the
+.Em sudoedit
+command and are ignored for all other commands.
+.It Em LOG_INPUT No and Em NOLOG_INPUT
+.sp
+These tags override the value of the
+.Em log_input
+flag on a per-command basis.
+For more information, see the description of
+.Em log_input
+in the
+.Sx SUDOERS OPTIONS
+section below.
+.It Em LOG_OUTPUT No and Em NOLOG_OUTPUT
+.sp
+These tags override the value of the
+.Em log_output
+flag on a per-command basis.
+For more information, see the description of
+.Em log_output
+in the
+.Sx SUDOERS OPTIONS
+section below.
+.It Em MAIL No and Em NOMAIL
+.sp
+These tags provide fine-grained control over whether
+mail will be sent when a user runs a command by
+overriding the value of the
+.Em mail_all_cmnds
+flag on a per-command basis.
+They have no effect when
+.Nm sudo
+is run with the
+.Fl l
+or
+.Fl v
+options.
+A
+.Em NOMAIL
+tag will also override the
+.Em mail_always
+and
+.Em mail_no_perms
+options.
+For more information, see the descriptions of
+.Em mail_all_cmnds ,
+.Em mail_always ,
+and
+.Em mail_no_perms
+in the
+.Sx SUDOERS OPTIONS
+section below.
+.It Em PASSWD No and Em NOPASSWD
+.sp
+By default,
+.Nm sudo
+requires that a user authenticate him or herself
+before running a command.
+This behavior can be modified via the
+.Li NOPASSWD
+tag.
+Like a
+.Li Runas_Spec ,
+the
+.Li NOPASSWD
+tag sets
+a default for the commands that follow it in the
+.Li Cmnd_Spec_List .
+Conversely, the
+.Li PASSWD
+tag can be used to reverse things.
+For example:
+.Bd -literal
+ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+.Ed
+.Pp
+would allow the user
+.Sy ray
+to run
+.Pa /bin/kill ,
+.Pa /bin/ls ,
+and
+.Pa /usr/bin/lprm
+as
+.Sy root
+on the machine rushmore without authenticating himself.
+If we only want
+.Sy ray
+to be able to
+run
+.Pa /bin/kill
+without a password the entry would be:
+.Bd -literal
+ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+.Ed
+.Pp
+Note, however, that the
+.Li PASSWD
+tag has no effect on users who are in the group specified by the
+.Em exempt_group
+setting.
+.Pp
+By default, if the
+.Li NOPASSWD
+tag is applied to any of a user's entries for the current host,
+the user will be able to run
+.Dq Li sudo -l
+without a password.
+Additionally, a user may only run
+.Dq Li sudo -v
+without a password if all of the user's entries for the current
+host have the
+.Li NOPASSWD
+tag.
+This behavior may be overridden via the
+.Em verifypw
+and
+.Em listpw
+options.
+.It Em SETENV No and Em NOSETENV
+.sp
+These tags override the value of the
+.Em setenv
+flag on a per-command basis.
+Note that if
+.Li SETENV
+has been set for a command, the user may disable the
+.Em env_reset
+flag from the command line via the
+.Fl E
+option.
+Additionally, environment variables set on the command
+line are not subject to the restrictions imposed by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep .
+As such, only trusted users should be allowed to set variables in this manner.
+If the command matched is
+.Sy ALL ,
+the
+.Li SETENV
+tag is implied for that command; this default may be overridden by use of the
+.Li NOSETENV
+tag.
+.El
+.Ss Wildcards
+.Nm sudo
+allows shell-style
+.Em wildcards
+(aka meta or glob characters)
+to be used in host names, path names and command line arguments in the
+.Em sudoers
+file.
+Wildcard matching is done via the
+.Xr glob 3
+and
+.Xr fnmatch 3
+functions as specified by
+.St -p1003.1 .
+.Bl -tag -width 8n
+.It Li *
+Matches any set of zero or more characters (including white space).
+.It Li \&?
+Matches any single character (including white space).
+.It Li [...]
+Matches any character in the specified range.
+.It Li [!...]
+Matches any character
+.Em not
+in the specified range.
+.It Li \ex
+For any character
+.Sq x ,
+evaluates to
+.Sq x .
+This is used to escape special characters such as:
+.Ql * ,
+.Ql \&? ,
+.Ql [\& ,
+and
+.Ql ]\& .
+.El
+.Pp
+.Bf -symbolic
+Note that these are not regular expressions.
+.Ef
+Unlike a regular expression there is no way to match one or more
+characters within a range.
+.Pp
+Character classes may be used if your system's
+.Xr glob 3
+and
+.Xr fnmatch 3
+functions support them.
+However, because the
+.Ql :\&
+character has special meaning in
+.Em sudoers ,
+it must be
+escaped.
+For example:
+.Bd -literal -offset 4n
+/bin/ls [[\e:\&alpha\e:\&]]*
+.Ed
+.Pp
+Would match any file name beginning with a letter.
+.Pp
+Note that a forward slash
+.Pq Ql /
+will
+.Em not
+be matched by
+wildcards used in the file name portion of the command.
+This is to make a path like:
+.Bd -literal -offset 4n
+/usr/bin/*
+.Ed
+.Pp
+match
+.Pa /usr/bin/who
+but not
+.Pa /usr/bin/X11/xterm .
+.Pp
+When matching the command line arguments, however, a slash
+.Em does
+get matched by wildcards since command line arguments may contain
+arbitrary strings and not just path names.
+.Pp
+.Bf -symbolic
+Wildcards in command line arguments should be used with care.
+.Ef
+.br
+Command line arguments are matched as a single, concatenated string.
+This mean a wildcard character such as
+.Ql \&?
+or
+.Ql *
+will match across word boundaries, which may be unexpected.
+For example, while a sudoers entry like:
+.Bd -literal -offset 4n
+%operator ALL = /bin/cat /var/log/messages*
+.Ed
+.Pp
+will allow command like:
+.Bd -literal -offset 4n
+$ sudo cat /var/log/messages.1
+.Ed
+.Pp
+It will also allow:
+.Bd -literal -offset 4n
+$ sudo cat /var/log/messages /etc/shadow
+.Ed
+.Pp
+which is probably not what was intended.
+In most cases it is better to do command line processing
+outside of the
+.Em sudoers
+file in a scripting language.
+.Ss Exceptions to wildcard rules
+The following exceptions apply to the above rules:
+.Bl -tag -width 8n
+.It Li \&""
+If the empty string
+.Li \&""
+is the only command line argument in the
+.Em sudoers
+file entry it means that command is not allowed to be run with
+.Em any
+arguments.
+.It sudoedit
+Command line arguments to the
+.Em sudoedit
+built-in command should always be path names, so a forward slash
+.Pq Ql /
+will not be matched by a wildcard.
+.El
+.Ss Including other files from within sudoers
+It is possible to include other
+.Em sudoers
+files from within the
+.Em sudoers
+file currently being parsed using the
+.Li @include
+and
+.Li @includedir
+directives.
+For compatibility with sudo versions prior to 1.9.1,
+.Li #include
+and
+.Li #includedir
+are also accepted.
+.Pp
+An include file can be used, for example, to keep a site-wide
+.Em sudoers
+file in addition to a local, per-machine file.
+For the sake of this example the site-wide
+.Em sudoers
+file will be
+.Pa /etc/sudoers
+and the per-machine one will be
+.Pa /etc/sudoers.local .
+To include
+.Pa /etc/sudoers.local
+from within
+.Pa /etc/sudoers
+one would use the following line in
+.Pa /etc/sudoers :
+.Bd -literal -offset 4n
+@include /etc/sudoers.local
+.Ed
+.Pp
+When
+.Nm sudo
+reaches this line it will suspend processing of the current file
+.Pq Pa /etc/sudoers
+and switch to
+.Pa /etc/sudoers.local .
+Upon reaching the end of
+.Pa /etc/sudoers.local ,
+the rest of
+.Pa /etc/sudoers
+will be processed.
+Files that are included may themselves include other files.
+A hard limit of 128 nested include files is enforced to prevent include
+file loops.
+.Pp
+The path to the include file may contain white space if it is
+escaped with a backslash
+.Pq Ql \e .
+Alternately, the entire path may be enclosed in double quotes
+.Pq \&"" ,
+in which case no escaping is necessary.
+To include a literal backslash in the path,
+.Ql \e\e
+should be used.
+.Pp
+If the path to the include file is not fully-qualified (does not
+begin with a
+.Ql / ) ,
+it must be located in the same directory as the sudoers file it was
+included from.
+For example, if
+.Pa /etc/sudoers
+contains the line:
+.Bd -literal -offset 4n
+.Li @include sudoers.local
+.Ed
+.Pp
+the file that will be included is
+.Pa /etc/sudoers.local .
+.Pp
+The file name may also include the
+.Li %h
+escape, signifying the short form of the host name.
+In other words, if the machine's host name is
+.Dq xerxes ,
+then
+.Bd -literal -offset 4n
+@include /etc/sudoers.%h
+.Ed
+.Pp
+will cause
+.Nm sudo
+to include the file
+.Pa /etc/sudoers.xerxes .
+.Pp
+The
+.Li @includedir
+directive can be used to create a
+.Pa sudoers.d
+directory that the system package manager can drop
+.Em sudoers
+file rules into as part of package installation.
+For example, given:
+.Bd -literal -offset 4n
+@includedir /etc/sudoers.d
+.Ed
+.Pp
+.Nm sudo
+will suspend processing of the current file and read each file in
+.Pa /etc/sudoers.d ,
+skipping file names that end in
+.Ql ~
+or contain a
+.Ql .\&
+character to avoid causing problems with package manager or editor
+temporary/backup files.
+Files are parsed in sorted lexical order.
+That is,
+.Pa /etc/sudoers.d/01_first
+will be parsed before
+.Pa /etc/sudoers.d/10_second .
+Be aware that because the sorting is lexical, not numeric,
+.Pa /etc/sudoers.d/1_whoops
+would be loaded
+.Em after
+.Pa /etc/sudoers.d/10_second .
+Using a consistent number of leading zeroes in the file names can be used
+to avoid such problems.
+After parsing the files in the directory, control returns to the
+file that contained the
+.Li @includedir
+directive.
+.Pp
+Note that unlike files included via
+.Li @include ,
+.Nm visudo
+will not edit the files in a
+.Li @includedir
+directory unless one of them contains a syntax error.
+It is still possible to run
+.Nm visudo
+with the
+.Fl f
+flag to edit the files directly, but this will not catch the
+redefinition of an
+.Em alias
+that is also present in a different file.
+.Ss Other special characters and reserved words
+The pound sign
+.Pq Ql #
+is used to indicate a comment (unless it is part of a #include
+directive or unless it occurs in the context of a user name and is
+followed by one or more digits, in which case it is treated as a
+user-ID).
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.Pp
+The reserved word
+.Sy ALL
+is a built-in
+.Em alias
+that always causes a match to succeed.
+It can be used wherever one might otherwise use a
+.Li Cmnd_Alias ,
+.Li User_Alias ,
+.Li Runas_Alias ,
+or
+.Li Host_Alias .
+Attempting to define an
+.Em alias
+named
+.Sy ALL
+will result in a syntax error.
+Please note that using
+.Sy ALL
+can be dangerous since in a command context, it allows the user to run
+.Em any
+command on the system.
+.Pp
+The following option names permitted in an
+.Li Option_Spec
+are also considered reserved words:
+.Li CHROOT ,
+.if \n(PS \{\
+.Li PRIVS ,
+.Li LIMITPRIVS ,
+.\}
+.if \n(SL \{\
+.Li ROLE ,
+.Li TYPE ,
+.\}
+.Li TIMEOUT ,
+.Li CWD ,
+.Li NOTBEFORE
+and
+.Li NOTAFTER .
+Attempting to define an
+.Em alias
+with the same name as one of the options will result in a syntax error.
+.Pp
+An exclamation point
+.Pq Ql \&!
+can be used as a logical
+.Em not
+operator in a list or
+.Em alias
+as well as in front of a
+.Li Cmnd .
+This allows one to exclude certain values.
+For the
+.Ql \&!
+operator to be effective, there must be something for it to exclude.
+For example, to match all users except for root one would use:
+.Bd -literal -offset 4n
+ALL,!root
+.Ed
+.Pp
+If the
+.Sy ALL ,
+is omitted, as in:
+.Bd -literal -offset 4n
+!root
+.Ed
+.Pp
+it would explicitly deny root but not match any other users.
+This is different from a true
+.Dq negation
+operator.
+.Pp
+Note, however, that using a
+.Ql \&!
+in conjunction with the built-in
+.Sy ALL
+alias to allow a user to run
+.Dq all but a few
+commands rarely works as intended (see
+.Sx SECURITY NOTES
+below).
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+.Pp
+White space between elements in a list as well as special syntactic
+characters in a
+.Em User Specification
+.Po
+.Ql =\& ,
+.Ql :\& ,
+.Ql (\& ,
+.Ql )\&
+.Pc
+is optional.
+.Pp
+The following characters must be escaped with a backslash
+.Pq Ql \e
+when used as part of a word (e.g., a user name or host name):
+.Ql \&! ,
+.Ql =\& ,
+.Ql :\& ,
+.Ql ,\& ,
+.Ql (\& ,
+.Ql )\& ,
+.Ql \e .
+.Sh SUDOERS OPTIONS
+.Nm sudo Ns 's
+behavior can be modified by
+.Li Default_Entry
+lines, as explained earlier.
+A list of all supported Defaults parameters, grouped by type, are listed below.
+.Pp
+.Sy Boolean Flags :
+.Bl -tag -width 16n
+.It always_query_group_plugin
+If a
+.Em group_plugin
+is configured, use it to resolve groups of the form %group as long
+as there is not also a system group of the same name.
+Normally, only groups of the form %:group are passed to the
+.Em group_plugin .
+This flag is
+.Em off
+by default.
+.It always_set_home
+If enabled,
+.Nm sudo
+will set the
+.Ev HOME
+environment variable to the home directory of the target user
+(which is the root user unless the
+.Fl u
+option is used).
+This flag is largely obsolete and has no effect unless the
+.Em env_reset
+flag has been disabled or
+.Ev HOME
+is present in the
+.Em env_keep
+list, both of which are strongly discouraged.
+This flag is
+.Em off
+by default.
+.It authenticate
+If set, users must authenticate themselves via a password (or other
+means of authentication) before they may run commands.
+This default may be overridden via the
+.Li PASSWD
+and
+.Li NOPASSWD
+tags.
+This flag is
+.Em on
+by default.
+.It case_insensitive_group
+If enabled, group names in
+.Em sudoers
+will be matched in a case insensitive manner.
+This may be necessary when users are stored in LDAP or AD.
+This flag is
+.Em on
+by default.
+.It case_insensitive_user
+If enabled, user names in
+.Em sudoers
+will be matched in a case insensitive manner.
+This may be necessary when groups are stored in LDAP or AD.
+This flag is
+.Em on
+by default.
+.It closefrom_override
+If set, the user may use the
+.Fl C
+option which overrides the default starting point at which
+.Nm sudo
+begins closing open file descriptors.
+This flag is
+.Em off
+by default.
+.It compress_io
+If set, and
+.Nm sudo
+is configured to log a command's input or output,
+the I/O logs will be compressed using
+.Sy zlib .
+This flag is
+.Em on
+by default when
+.Nm sudo
+is compiled with
+.Sy zlib
+support.
+.It exec_background
+By default,
+.Nm sudo
+runs a command as the foreground process as long as
+.Nm sudo
+itself is running in the foreground.
+When the
+.Em exec_background
+flag is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+.Em use_pty
+flag), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+.Dv SIGTTIN
+signal (or
+.Dv SIGTTOU
+in the case of terminal settings).
+If this happens when
+.Nm sudo
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+.Nm sudo
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+.Em sudo
+behavior or when the command is not being run in a pseudo-terminal.
+.Pp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+.Fn tcgetattr
+and
+.Fn tcsetattr
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+.Dv SIGTTIN
+or
+.Dv SIGTTOU
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+.Dv SIGTOP )
+will not be automatically foregrounded.
+Some versions of the linux
+.Xr su 1
+command behave this way.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+It has no effect unless I/O logging is enabled or the
+.Em use_pty
+flag is enabled.
+.It env_editor
+If set,
+.Nm visudo
+will use the value of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables before falling back on the default editor list.
+Note that
+.Nm visudo
+is typically run as root so this flag may allow a user with
+.Nm visudo
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+.Dq safe
+editors int the
+.Em editor
+variable.
+.Nm visudo
+will then only use
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+if they match a value specified in
+.Em editor .
+If the
+.Em env_reset
+flag is enabled, the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+and/or
+.Ev EDITOR
+environment variables must be present in the
+.Em env_keep
+list for the
+.Em env_editor
+flag to function when
+.Nm visudo
+is invoked via
+.Nm sudo .
+This flag is
+.Em @env_editor@
+by default.
+.It env_reset
+If set,
+.Nm sudo
+will run the command in a minimal environment containing the
+.Ev TERM ,
+.Ev PATH ,
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev LOGNAME ,
+.Ev USER
+and
+.Ev SUDO_*
+variables.
+Any variables in the caller's environment or in the file specified
+by the
+.Em restricted_env_file
+setting that match the
+.Li env_keep
+and
+.Li env_check
+lists are then added, followed by any variables present in the file
+specified by the
+.Em env_file
+setting (if any).
+The contents of the
+.Li env_keep
+and
+.Li env_check
+lists, as modified by global Defaults parameters in
+.Em sudoers ,
+are displayed when
+.Nm sudo
+is run by root with the
+.Fl V
+option.
+If the
+.Em secure_path
+setting is enabled, its value will be used for the
+.Ev PATH
+environment variable.
+This flag is
+.Em @env_reset@
+by default.
+.It fast_glob
+Normally,
+.Nm sudo
+uses the
+.Xr glob 3
+function to do shell-style globbing when matching path names.
+However, since it accesses the file system,
+.Xr glob 3
+can take a long time to complete for some patterns, especially
+when the pattern references a network file system that is mounted
+on demand (auto mounted).
+The
+.Em fast_glob
+flag causes
+.Nm sudo
+to use the
+.Xr fnmatch 3
+function, which does not access the file system to do its matching.
+The disadvantage of
+.Em fast_glob
+is that it is unable to match relative path names such as
+.Pa ./ls
+or
+.Pa ../bin/ls .
+This has security implications when path names that include globbing
+characters are used with the negation operator,
+.Ql !\& ,
+as such rules can be trivially bypassed.
+As such, this flag should not be used when the
+.Em sudoers
+file contains rules that contain negated path names which include globbing
+characters.
+This flag is
+.Em off
+by default.
+.It fqdn
+Set this flag if you want to put fully qualified host names in the
+.Em sudoers
+file when the local host name (as returned by the
+.Li hostname
+command) does not contain the domain name.
+In other words, instead of myhost you would use myhost.mydomain.edu.
+You may still use the short form if you wish (and even mix the two).
+This flag is only effective when the
+.Dq canonical
+host name, as returned by the
+.Fn getaddrinfo
+or
+.Fn gethostbyname
+function, is a fully-qualified domain name.
+This is usually the case when the system is configured to use DNS
+for host name resolution.
+.Pp
+If the system is configured to use the
+.Pa /etc/hosts
+file in preference to DNS, the
+.Dq canonical
+host name may not be fully-qualified.
+The order that sources are queried for host name resolution
+is usually specified in the
+.Pa @nsswitch_conf@ ,
+.Pa @netsvc_conf@ ,
+.Pa /etc/host.conf ,
+or, in some cases,
+.Pa /etc/resolv.conf
+file.
+In the
+.Pa /etc/hosts
+file, the first host name of the entry is considered to be the
+.Dq canonical
+name; subsequent names are aliases that are not used by
+.Nm .
+For example, the following hosts file line for the machine
+.Dq xyzzy
+has the fully-qualified domain name as the
+.Dq canonical
+host name, and the short version as an alias.
+.sp
+.Dl 192.168.1.1 xyzzy.sudo.ws xyzzy
+.sp
+If the machine's hosts file entry is not formatted properly, the
+.Em fqdn
+flag will not be effective if it is queried before DNS.
+.Pp
+Beware that when using DNS for host name resolution, turning on
+.Em fqdn
+requires
+.Nm
+to make DNS lookups which renders
+.Nm sudo
+unusable if DNS stops working (for example if the machine is disconnected
+from the network).
+Also note that just like with the hosts file, you must use the
+.Dq canonical
+name as DNS knows it.
+That is, you may not use a host alias
+.Po
+.Li CNAME
+entry
+.Pc
+due to performance issues and the fact that there is no way to get all
+aliases from DNS.
+.Pp
+This flag is
+.Em @fqdn@
+by default.
+.It ignore_audit_errors
+Allow commands to be run even if
+.Nm
+cannot write to the audit log.
+If enabled, an audit log write failure is not treated as a fatal error.
+If disabled, a command may only be run after the audit event is successfully
+written.
+This flag is only effective on systems for which
+.Nm
+supports audit logging, including
+.Fx ,
+Linux, macOS and Solaris.
+This flag is
+.Em on
+by default.
+.It ignore_dot
+If set,
+.Nm sudo
+will ignore "." or "" (both denoting current directory) in the
+.Ev PATH
+environment variable; the
+.Ev PATH
+itself is not modified.
+This flag is
+.Em @ignore_dot@
+by default.
+.It ignore_iolog_errors
+Allow commands to be run even if
+.Nm
+cannot write to the I/O log (local or remote).
+If enabled, an I/O log write failure is not treated as a fatal error.
+If disabled, the command will be terminated if the I/O log cannot be written to.
+This flag is
+.Em off
+by default.
+.It ignore_logfile_errors
+Allow commands to be run even if
+.Nm
+cannot write to the log file.
+If enabled, a log file write failure is not treated as a fatal error.
+If disabled, a command may only be run after the log file entry is successfully
+written.
+This flag only has an effect when
+.Nm
+is configured to use file-based logging via the
+.Em logfile
+setting.
+This flag is
+.Em on
+by default.
+.It ignore_local_sudoers
+If set via LDAP, parsing of
+.Pa @sysconfdir@/sudoers
+will be skipped.
+This is intended for Enterprises that wish to prevent the usage of local
+sudoers files so that only LDAP is used.
+This thwarts the efforts of rogue operators who would attempt to add roles to
+.Pa @sysconfdir@/sudoers .
+When this flag is enabled,
+.Pa @sysconfdir@/sudoers
+does not even need to exist.
+Since this flag tells
+.Nm sudo
+how to behave when no specific LDAP entries have been matched, this
+sudoOption is only meaningful for the
+.Li cn=defaults
+section.
+This flag is
+.Em off
+by default.
+.It ignore_unknown_defaults
+If set,
+.Nm sudo
+will not produce a warning if it encounters an unknown Defaults entry
+in the
+.Em sudoers
+file or an unknown sudoOption in LDAP.
+This flag is
+.Em off
+by default.
+.It insults
+If set,
+.Nm sudo
+will insult users when they enter an incorrect password.
+This flag is
+.Em @insults@
+by default.
+.It log_allowed
+If set,
+.Nm
+will log commands allowed by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.29 or higher.
+.It log_denied
+If set,
+.Nm
+will log commands denied by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.29 or higher.
+.It log_host
+If set, the host name will be included in log entries written to
+the file configured by the
+.Em logfile
+setting.
+This flag is
+.Em off
+by default.
+.It log_input
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal and log all user input.
+If the standard input is not connected to the user's tty, due to
+I/O redirection or because the command is part of a pipeline, that
+input is also captured and stored in a separate log file.
+Anything sent to the standard input will be consumed, regardless of
+whether or not the command run via
+.Nm sudo
+is actually reading the standard input.
+This may have unexpected results when using
+.Nm sudo
+in a shell script that expects to process the standard input.
+For more information about I/O logging, see the
+.Sx "I/O LOG FILES"
+section.
+This flag is
+.Em off
+by default.
+.It log_output
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal and log all output that is sent
+to the screen, similar to the
+.Xr script 1
+command.
+For more information about I/O logging, see the
+.Sx "I/O LOG FILES"
+section.
+This flag is
+.Em off
+by default.
+.It log_server_keepalive
+If set,
+.Nm sudo
+will enable the TCP keepalive socket option on the connection to the log server.
+This enables the periodic transmission of keepalive messages to the server.
+If the server does not respond to a message, the connection will
+be closed and the running command will be terminated unless the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_verify
+If set, the server certificate received during the TLS handshake
+must be valid and it must contain either the server name (from
+.Em log_servers )
+or its IP address.
+If either of these conditions is not met, the TLS handshake will fail.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_year
+If set, the four-digit year will be logged in the (non-syslog)
+.Nm sudo
+log file.
+This flag is
+.Em off
+by default.
+.It long_otp_prompt
+When validating with a One Time Password (OTP) scheme such as
+.Sy S/Key
+or
+.Sy OPIE ,
+a two-line prompt is used to make it easier
+to cut and paste the challenge to a local window.
+It's not as pretty as the default but some people find it more convenient.
+This flag is
+.Em @long_otp_prompt@
+by default.
+.It mail_all_cmnds
+Send mail to the
+.Em mailto
+user every time a user attempts to run a command via
+.Nm sudo
+(this includes
+.Nm sudoedit ) .
+No mail will be sent if the user runs
+.Nm sudo
+with the
+.Fl l
+or
+.Fl v
+option unless there is an authentication error and the
+.Em mail_badpass
+flag is also set.
+This flag is
+.Em off
+by default.
+.It mail_always
+Send mail to the
+.Em mailto
+user every time a user runs
+.Nm sudo .
+This flag is
+.Em off
+by default.
+.It mail_badpass
+Send mail to the
+.Em mailto
+user if the user running
+.Nm sudo
+does not enter the correct password.
+If the command the user is attempting to run is not permitted by
+.Nm
+and one of the
+.Em mail_all_cmnds ,
+.Em mail_always ,
+.Em mail_no_host ,
+.Em mail_no_perms
+or
+.Em mail_no_user
+flags are set, this flag will have no effect.
+This flag is
+.Em off
+by default.
+.It mail_no_host
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user exists in the
+.Em sudoers
+file, but is not allowed to run commands on the current host.
+This flag is
+.Em @mail_no_host@
+by default.
+.It mail_no_perms
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user is allowed to use
+.Nm sudo
+but the command they are trying is not listed in their
+.Em sudoers
+file entry or is explicitly denied.
+This flag is
+.Em @mail_no_perms@
+by default.
+.It mail_no_user
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user is not in the
+.Em sudoers
+file.
+This flag is
+.Em @mail_no_user@
+by default.
+.It match_group_by_gid
+By default,
+.Nm
+will look up each group the user is a member of by group-ID to
+determine the group name (this is only done once).
+The resulting list of the user's group names is used when matching
+groups listed in the
+.Em sudoers
+file.
+This works well on systems where the number of groups listed in the
+.Em sudoers
+file is larger than the number of groups a typical user belongs to.
+On systems where group lookups are slow, where users may belong
+to a large number of groups, and where the number of groups listed
+in the
+.Em sudoers
+file is relatively small, it may be prohibitively expensive and
+running commands via
+.Nm sudo
+may take longer than normal.
+On such systems it may be faster to use the
+.Em match_group_by_gid
+flag to avoid resolving the user's group-IDs to group names.
+In this case,
+.Nm
+must look up any group name listed in the
+.Em sudoers
+file and use the group-ID instead of the group name when determining
+whether the user is a member of the group.
+.Pp
+Note that if
+.Em match_group_by_gid
+is enabled, group database lookups performed by
+.Nm
+will be keyed by group name as opposed to group-ID.
+On systems where there are multiple sources for the group database,
+it is possible to have conflicting group names or group-IDs in the local
+.Pa /etc/group
+file and the remote group database.
+On such systems, enabling or disabling
+.Em match_group_by_gid
+can be used to choose whether group database queries are performed
+by name (enabled) or ID (disabled), which may aid in working around
+group entry conflicts.
+.Pp
+The
+.Em match_group_by_gid
+flag has no effect when
+.Em sudoers
+data is stored in LDAP.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.18 or higher.
+.It netgroup_tuple
+If set, netgroup lookups will be performed using the full netgroup
+tuple: host name, user name and domain (if one is set).
+Historically,
+.Nm sudo
+only matched the user name and domain for netgroups used in a
+.Li User_List
+and only matched the host name and domain for netgroups used in a
+.Li Host_List .
+This flag is
+.Em off
+by default.
+.It noexec
+If set, all commands run via
+.Nm sudo
+will behave as if the
+.Li NOEXEC
+tag has been set, unless overridden by an
+.Li EXEC
+tag.
+See the description of
+.Em EXEC and NOEXEC
+above as well as the
+.Sx Preventing shell escapes
+section at the end of this manual.
+This flag is
+.Em off
+by default.
+.It pam_acct_mgmt
+On systems that use PAM for authentication,
+.Nm sudo
+will perform PAM account validation for the invoking user by default.
+The actual checks performed depend on which PAM modules are configured.
+If enabled, account validation will be performed regardless of whether
+or not a password is required.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.28 or higher.
+.It pam_rhost
+On systems that use PAM for authentication,
+.Nm sudo
+will set the PAM remote host value to the name of the local host
+when the
+.Em pam_rhost
+flag is enabled.
+On Linux systems, enabling
+.Em pam_rhost
+may result in DNS lookups of the local host name when PAM is initialized.
+On Solaris versions prior to Solaris 8,
+.Em pam_rhost
+must be enabled if
+.Em pam_ruser
+is also enabled to avoid a crash in the Solaris PAM implementation.
+.Pp
+This flag is
+.Em off
+by default on systems other than Solaris.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It pam_ruser
+On systems that use PAM for authentication,
+.Nm sudo
+will set the PAM remote user value to the name of the user that invoked sudo
+when the
+.Em pam_ruser
+flag is enabled.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It pam_session
+On systems that use PAM for authentication,
+.Nm sudo
+will create a new PAM session for the command to be run in.
+Unless
+.Nm sudo
+is given the
+.Fl i
+or
+.Fl s
+options, PAM session modules are run with the
+.Dq silent
+flag enabled.
+This prevents last login information from being displayed for every
+command on some systems.
+Disabling
+.Em pam_session
+may be needed on older PAM implementations or on operating systems where
+opening a PAM session changes the utmp or wtmp files.
+If PAM session support is disabled, resource limits may not be updated
+for the command being run.
+If
+.Em pam_session ,
+.Em pam_setcred ,
+and
+.Em use_pty
+are disabled,
+.Em log_servers
+has not been set and I/O logging has not been configured,
+.Nm sudo
+will execute the command directly instead of running it as a child
+process.
+This flag is
+.Em @pam_session@
+by default.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+.It pam_setcred
+On systems that use PAM for authentication,
+.Nm sudo
+will attempt to establish credentials for the target user by default,
+if supported by the underlying authentication system.
+One example of a credential is a Kerberos ticket.
+If
+.Em pam_session ,
+.Em pam_setcred ,
+and
+.Em use_pty
+are disabled,
+.Em log_servers
+has not been set and I/O logging has not been configured,
+.Nm sudo
+will execute the command directly instead of running it as a child
+process.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It passprompt_override
+If set, the prompt specified by
+.Em passprompt
+or the
+.Ev SUDO_PROMPT
+environment variable will always be used and will replace the
+prompt provided by a PAM module or other authentication method.
+This flag is
+.Em off
+by default.
+.It path_info
+Normally,
+.Nm sudo
+will tell the user when a command could not be
+found in their
+.Ev PATH
+environment variable.
+Some sites may wish to disable this as it could be used to gather
+information on the location of executables that the normal user does
+not have access to.
+The disadvantage is that if the executable is simply not in the user's
+.Ev PATH ,
+.Nm sudo
+will tell the user that they are not allowed to run it, which can be confusing.
+This flag is
+.Em @path_info@
+by default.
+.It preserve_groups
+By default,
+.Nm sudo
+will initialize the group vector to the list of groups the target user is in.
+When
+.Em preserve_groups
+is set, the user's existing group vector is left unaltered.
+The real and effective group-IDs, however, are still set to match the
+target user.
+This flag is
+.Em off
+by default.
+.It pwfeedback
+By default,
+.Nm sudo
+reads the password like most other Unix programs,
+by turning off echo until the user hits the return (or enter) key.
+Some users become confused by this as it appears to them that
+.Nm sudo
+has hung at this point.
+When
+.Em pwfeedback
+is set,
+.Nm sudo
+will provide visual feedback when the user presses a key.
+Note that this does have a security impact as an onlooker may be able to
+determine the length of the password being entered.
+This flag is
+.Em off
+by default.
+.It requiretty
+If set,
+.Nm sudo
+will only run when the user is logged in to a real tty.
+When this flag is set,
+.Nm sudo
+can only be run from a login session and not via other means such as
+.Xr cron @mansectsu@
+or cgi-bin scripts.
+This flag is
+.Em off
+by default.
+.It root_sudo
+If set, root is allowed to run
+.Nm sudo
+too.
+Disabling this prevents users from
+.Dq chaining
+.Nm sudo
+commands to get a root shell by doing something like
+.Dq Li sudo sudo /bin/sh .
+Note, however, that turning off
+.Em root_sudo
+will also prevent root from running
+.Nm sudoedit .
+Disabling
+.Em root_sudo
+provides no real additional security; it exists purely for historical reasons.
+This flag is
+.Em @root_sudo@
+by default.
+.It rootpw
+If set,
+.Nm sudo
+will prompt for the root password instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+.Em off
+by default.
+.It runas_allow_unknown_id
+If enabled, allow matching of runas user and group IDs that are
+not present in the password or group databases.
+In addition to explicitly matching unknown user or group IDs in a
+.Li Runas_List ,
+this option also allows the
+.Sy ALL
+alias to match unknown IDs.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.30 or higher.
+Older versions of
+.Nm sudo
+always allowed matching of unknown user and group IDs.
+.It runas_check_shell
+If enabled,
+.Nm sudo
+will only run commands as a user whose shell appears in the
+.Pa /etc/shells
+file, even if the invoking user's
+.Li Runas_List
+would otherwise permit it.
+If no
+.Pa /etc/shells
+file is present, a system-dependent list of built-in default shells is used.
+On many operating systems, system users such as
+.Dq bin ,
+do not have a valid shell and this flag can be used to prevent
+commands from being run as those users.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.30 or higher.
+.It runaspw
+If set,
+.Nm sudo
+will prompt for the password of the user defined by the
+.Em runas_default
+option (defaults to
+.Li @runas_default@ )
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+.Em off
+by default.
+.if \n(SL \{\
+.It selinux
+If enabled, the user may specify an SELinux role and/or type to use
+when running the command, as permitted by the SELinux policy.
+If SELinux is disabled on the system, this flag has no effect.
+This flag is
+.Em on
+by default.
+.\}
+.It set_home
+If enabled and
+.Nm sudo
+is invoked with the
+.Fl s
+option, the
+.Ev HOME
+environment variable will be set to the home directory of the target
+user (which is the root user unless the
+.Fl u
+option is used).
+This flag is largely obsolete and has no effect unless the
+.Em env_reset
+flag has been disabled or
+.Ev HOME
+is present in the
+.Em env_keep
+list, both of which are strongly discouraged.
+This flag is
+.Em off
+by default.
+.It set_logname
+Normally,
+.Nm sudo
+will set the
+.Ev LOGNAME
+and
+.Ev USER
+environment variables to the name of the target user (usually root unless the
+.Fl u
+option is given).
+However, since some programs (including the RCS revision control system) use
+.Ev LOGNAME
+to determine the real identity of the user, it may be desirable to
+change this behavior.
+This can be done by negating the set_logname option.
+Note that
+.Em set_logname
+will have no effect
+if the
+.Em env_reset
+option has not been disabled and the
+.Em env_keep
+list contains
+.Ev LOGNAME
+or
+.Ev USER .
+This flag is
+.Em on
+by default.
+.It set_utmp
+When enabled,
+.Nm sudo
+will create an entry in the utmp (or utmpx) file when a pseudo-terminal
+is allocated.
+A pseudo-terminal is allocated by
+.Nm sudo
+when it is running in a terminal and one or more of the
+.Em log_input ,
+.Em log_output
+or
+.Em use_pty
+flags is enabled.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+This flag is
+.Em on
+by default.
+.It setenv
+Allow the user to disable the
+.Em env_reset
+option from the command line via the
+.Fl E
+option.
+Additionally, environment variables set via the command line are
+not subject to the restrictions imposed by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep .
+As such, only trusted users should be allowed to set variables in this manner.
+This flag is
+.Em off
+by default.
+.It shell_noargs
+If set and
+.Nm sudo
+is invoked with no arguments it acts as if the
+.Fl s
+option had been given.
+That is, it runs a shell as root (the shell is determined by the
+.Ev SHELL
+environment variable if it is set, falling back on the shell listed
+in the invoking user's /etc/passwd entry if not).
+This flag is
+.Em off
+by default.
+.It stay_setuid
+Normally, when
+.Nm sudo
+executes a command the real and effective UIDs are set to the target
+user (root by default).
+This option changes that behavior such that the real UID is left
+as the invoking user's UID.
+In other words, this makes
+.Nm sudo
+act as a set-user-ID wrapper.
+This can be useful on systems that disable some potentially
+dangerous functionality when a program is run set-user-ID.
+This option is only effective on systems that support either the
+.Xr setreuid 2
+or
+.Xr setresuid 2
+system call.
+This flag is
+.Em off
+by default.
+.It sudoedit_checkdir
+If set,
+.Nm sudoedit
+will check all directory components of the path to be edited for writability
+by the invoking user.
+Symbolic links will not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+.Nm sudoedit
+is run by root.
+On some systems, if all directory components of the path to be edited
+are not readable by the target user,
+.Nm sudoedit
+will be unable to edit the file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting was first introduced in version 1.8.15 but initially
+suffered from a race condition.
+The check for symbolic links in writable intermediate directories
+was added in version 1.8.16.
+.It sudoedit_follow
+By default,
+.Nm sudoedit
+will not follow symbolic links when opening files.
+The
+.Em sudoedit_follow
+option can be enabled to allow
+.Nm sudoedit
+to open symbolic links.
+It may be overridden on a per-command basis by the
+.Em FOLLOW
+and
+.Em NOFOLLOW
+tags.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.15 or higher.
+.It syslog_pid
+When logging via
+.Xr syslog 3 ,
+include the process ID in the log entry.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.21 or higher.
+.It targetpw
+If set,
+.Nm sudo
+will prompt for the password of the user specified
+by the
+.Fl u
+option (defaults to
+.Li root )
+instead of the password of the invoking user
+when running a command or editing a file.
+Note that this flag precludes the use of a user-ID not listed in the passwd
+database as an argument to the
+.Fl u
+option.
+This flag is
+.Em off
+by default.
+.It tty_tickets
+If set, users must authenticate on a per-tty basis.
+With this flag enabled,
+.Nm sudo
+will use a separate record in the time stamp file for each terminal.
+If disabled, a single record is used for all login sessions.
+.Pp
+This option has been superseded by the
+.Em timestamp_type
+option.
+.It umask_override
+If set,
+.Nm sudo
+will set the umask as specified in the
+.Em sudoers
+file without modification.
+This makes it possible to specify a umask in the
+.Em sudoers
+file that is more permissive than the user's own umask and matches
+historical behavior.
+If
+.Em umask_override
+is not set,
+.Nm sudo
+will set the umask to be the union of the user's umask and what is specified in
+.Em sudoers .
+This flag is
+.Em @umask_override@
+by default.
+.if \n(LC \{\
+.It use_loginclass
+If set,
+.Nm sudo
+will apply the defaults specified for the target user's login class
+if one exists.
+Only available if
+.Nm sudo
+is configured with the
+.Li --with-logincap
+option.
+This flag is
+.Em off
+by default.
+.\}
+.It use_netgroups
+If set, netgroups (prefixed with
+.Ql + ) ,
+may be used in place of a user or host.
+For LDAP-based sudoers, netgroup support requires an expensive
+sub-string match on the server unless the
+.Sy NETGROUP_BASE
+directive is present in the
+.Pa @ldap_conf@
+file.
+If netgroups are not needed, this option can be disabled to reduce the
+load on the LDAP server.
+This flag is
+.Em on
+by default.
+.It use_pty
+If set, and
+.Nm sudo
+is running in a terminal, the command will be run in a pseudo-terminal
+(even if no I/O logging is being done).
+If the
+.Nm sudo
+process is not attached to a terminal,
+.Em use_pty
+has no effect.
+.Pp
+A malicious program run under
+.Nm sudo
+may be capable of injecting commands into the user's
+terminal or running a background process that retains access to the
+user's terminal device even after the main program has finished
+executing.
+By running the command in a separate pseudo-terminal, this attack is
+no longer possible.
+This flag is
+.Em off
+by default.
+.It user_command_timeouts
+If set, the user may specify a timeout on the command line.
+If the timeout expires before the command has exited, the
+command will be terminated.
+If a timeout is specified both in the
+.Pa sudoers
+file and on the command line, the smaller of the two timeouts will be used.
+See the
+.Li Timeout_Spec
+section for a description of the timeout syntax.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It utmp_runas
+If set,
+.Nm sudo
+will store the name of the runas user when updating the utmp (or utmpx) file.
+By default,
+.Nm sudo
+stores the name of the invoking user.
+This flag is
+.Em off
+by default.
+.It visiblepw
+By default,
+.Nm sudo
+will refuse to run if the user must enter a password but it is not
+possible to disable echo on the terminal.
+If the
+.Em visiblepw
+flag is set,
+.Nm sudo
+will prompt for a password even when it would be visible on the screen.
+This makes it possible to run things like
+.Dq Li ssh somehost sudo ls
+since by default,
+.Xr ssh 1
+does
+not allocate a tty when running a command.
+This flag is
+.Em off
+by default.
+.El
+.Pp
+.Sy Integers :
+.Bl -tag -width 16n
+.It closefrom
+Before it executes a command,
+.Nm sudo
+will close all open file descriptors other than standard input,
+standard output and standard error (ie: file descriptors 0-2).
+The
+.Em closefrom
+option can be used to specify a different file descriptor at which
+to start closing.
+The default is
+.Li 3 .
+.It command_timeout
+The maximum amount of time a command is allowed to run before
+it is terminated.
+See the
+.Li Timeout_Spec
+section for a description of the timeout syntax.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It log_server_timeout
+The maximum amount of time to wait when connecting to a log server
+or waiting for a server response.
+See the
+.Li Timeout_Spec
+section for a description of the timeout syntax.
+The default value is 30 seconds.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It maxseq
+The maximum sequence number that will be substituted for the
+.Dq Li %{seq}
+escape in the I/O log file (see the
+.Em iolog_dir
+description below for more information).
+While the value substituted for
+.Dq Li %{seq}
+is in base 36,
+.Em maxseq
+itself should be expressed in decimal.
+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.
+.Pp
+Once the local sequence number reaches the value of
+.Em maxseq ,
+it will
+.Dq roll over
+to zero, after which
+.Nm
+will truncate and re-use any existing I/O log path names.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+.It passwd_tries
+The number of tries a user gets to enter his/her password before
+.Nm sudo
+logs the failure and exits.
+The default is
+.Li @passwd_tries@ .
+.It syslog_maxlen
+On many systems,
+.Xr syslog 3
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+.Nm
+creates log messages up to 980 bytes which corresponds to the
+historic
+.Bx
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname and program name.
+To prevent syslog messages from being truncated,
+.Nm
+will split up log messages that are larger than
+.Em syslog_maxlen
+bytes.
+When a message is split, additional parts will include the string
+.Dq Pq command continued
+after the user name and before the continued command line arguments.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.El
+.Pp
+.Sy Integers that can be used in a boolean context :
+.Bl -tag -width 16n
+.It loglinelen
+Number of characters per line for the file log.
+This value is used to decide when to wrap lines for nicer log files.
+This has no effect on the syslog log file, only the file log.
+The default is
+.Li @loglen@
+(use 0 or negate the option to disable word wrap).
+.It passwd_timeout
+Number of minutes before the
+.Nm sudo
+password prompt times out, or
+.Li 0
+for no timeout.
+The timeout may include a fractional component
+if minute granularity is insufficient, for example
+.Li 2.5 .
+The
+default is
+.Li @password_timeout@ .
+.It timestamp_timeout
+Number of minutes that can elapse before
+.Nm sudo
+will ask for a passwd again.
+The timeout may include a fractional component if
+minute granularity is insufficient, for example
+.Li 2.5 .
+The default is
+.Li @timeout@ .
+Set this to
+.Li 0
+to always prompt for a password.
+If set to a value less than
+.Li 0
+the user's time stamp will not expire until the system is rebooted.
+This can be used to allow users to create or delete their own time stamps via
+.Dq Li sudo -v
+and
+.Dq Li sudo -k
+respectively.
+.It umask
+File mode creation mask to use when running the command.
+Negate this option or set it to 0777 to prevent
+.Nm
+from changing the umask.
+Unless the
+.Em umask_override
+flag is set, the actual umask will be the union of the
+user's umask and the value of the
+.Em umask
+setting, which defaults to
+.Li @sudo_umask@ .
+This guarantees
+that
+.Nm sudo
+never lowers the umask when running a command.
+.Pp
+If
+.Em umask
+is explicitly set in
+.Em sudoers ,
+it will override any umask setting in PAM or login.conf.
+If
+.Em umask
+is not set in
+.Em sudoers ,
+the umask specified by PAM or login.conf will take precedence.
+The umask setting in PAM is not used for
+.Nm sudoedit ,
+which does not create a new PAM session.
+.El
+.Pp
+.Sy Strings :
+.Bl -tag -width 16n
+.It authfail_message
+Message that is displayed after a user fails to authenticate.
+The message may include the
+.Ql %d
+escape which will expand to the number of failed password attempts.
+If set, it overrides the default message,
+.Li %d incorrect password attempt(s) .
+.It badpass_message
+Message that is displayed if a user enters an incorrect password.
+The default is
+.Li @badpass_message@
+unless insults are enabled.
+.It editor
+A colon
+.Pq Ql :\&
+separated list of editors path names used by
+.Nm sudoedit
+and
+.Nm visudo .
+For
+.Nm sudoedit ,
+this list is used to find an editor when none of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables are set to an editor that exists and is executable.
+For
+.Nm visudo ,
+it is used as a white list of allowed editors;
+.Nm visudo
+will choose the editor that matches the user's
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variable if possible, or the first editor in the
+list that exists and is executable if not.
+Unless invoked as
+.Nm sudoedit ,
+.Nm sudo
+does not preserve the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables unless they are present in the
+.Em env_keep
+list or the
+.Em env_reset
+option is disabled.
+The default is
+.Pa @editor@ .
+.It iolog_dir
+The top-level directory to use when constructing the path name for
+the input/output log directory.
+Only used if the
+.Em log_input
+or
+.Em log_output
+options are enabled or when the
+.Li LOG_INPUT
+or
+.Li LOG_OUTPUT
+tags are present for a command.
+The session sequence number, if any, is stored in the directory.
+The default is
+.Pa @iolog_dir@ .
+.Pp
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It Li %{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}
+expanded to the invoking user's login name
+.It Li %{group}
+expanded to the name of the invoking user's real group-ID
+.It Li %{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.It Li %{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.It Li %{hostname}
+expanded to the local host name without the domain name
+.It Li %{command}
+expanded to the base name of the command being run
+.El
+.Pp
+In addition, any escape sequences supported by the system's
+.Xr strftime 3
+function will be expanded.
+.Pp
+To include a literal
+.Ql %
+character, the string
+.Ql %%
+should be used.
+.It iolog_file
+The path name, relative to
+.Em iolog_dir ,
+in which to store input/output logs when the
+.Em log_input
+or
+.Em log_output
+options are enabled or when the
+.Li LOG_INPUT
+or
+.Li LOG_OUTPUT
+tags are present for a command.
+Note that
+.Em iolog_file
+may contain directory components.
+The default is
+.Dq Li %{seq} .
+.Pp
+See the
+.Em iolog_dir
+option above for a list of supported percent
+.Pq Ql %
+escape sequences.
+.Pp
+In addition to the escape sequences, path names that end in six or
+more
+.Li X Ns s
+will have the
+.Li X Ns s
+replaced with a unique combination of digits and letters, similar to the
+.Xr mktemp 3
+function.
+.Pp
+If the path created by concatenating
+.Em iolog_dir
+and
+.Em iolog_file
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+.Em iolog_file
+ends in six or
+more
+.Li X Ns s .
+.It iolog_flush
+If set,
+.Nm sudo
+will flush I/O log data to disk after each write instead of buffering it.
+This makes it possible to view the logs in real-time as the program
+is executing but may significantly reduce the effectiveness of I/O
+log compression.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It iolog_group
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+.Em iolog_group
+is not set,
+the primary group-ID of the user specified by
+.Em iolog_user
+is used.
+If neither
+.Em iolog_group
+nor
+.Em iolog_user
+are set, I/O log files and directories are created with group-ID 0.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It iolog_mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+.Em iolog_mode .
+Defaults to 0600 (read and write by user only).
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It iolog_user
+The user name to look up when setting the user and group-IDs on new
+I/O log files and directories.
+If
+.Em iolog_group
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.Pp
+This setting can be useful when the I/O logs are stored on a Network
+File System (NFS) share.
+Having a dedicated user own the I/O log files means that
+.Nm
+does not write to the log files as user-ID 0, which is usually
+not permitted by NFS.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It lecture_status_dir
+The directory in which
+.Nm sudo
+stores per-user lecture status files.
+Once a user has received the lecture, a zero-length file is
+created in this directory so that
+.Nm sudo
+will not lecture the user again.
+This directory should
+.Em not
+be cleared when the system reboots.
+The default is
+.Pa @vardir@/lectured .
+.if \n(PS \{\
+.It limitprivs
+The default Solaris limit privileges to use when constructing a new
+privilege set for a command.
+This bounds all privileges of the executing process.
+The default limit privileges may be overridden on a per-command basis in
+.Em sudoers .
+This option is only available if
+.Nm
+is built on Solaris 10 or higher.
+.\}
+.It log_server_cabundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+This setting has no effect unless
+.Em log_servers
+is set and the remote log server is secured with TLS.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_peer_cert
+The path to the client's certificate file, in PEM format.
+This setting is required when
+.Em log_servers
+is set and the remote log server is secured with TLS.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_peer_key
+The path to the client's private key file, in PEM format.
+This setting is required when
+.Em log_servers
+is set and the remote log server is secured with TLS.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It mailsub
+Subject of the mail sent to the
+.Em mailto
+user.
+The escape
+.Li %h
+will expand to the host name of the machine.
+Default is
+.Dq Li @mailsub@ .
+.It noexec_file
+As of
+.Nm sudo
+version 1.8.1 this option is no longer supported.
+The path to the noexec file should now be set in the
+.Xr sudo.conf @mansectform@
+file.
+.It pam_login_service
+On systems that use PAM for authentication, this is the service
+name used when the
+.Fl i
+option is specified.
+The default value is
+.Dq Li @pam_login_service@ .
+See the description of
+.Em pam_service
+for more information.
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It pam_service
+On systems that use PAM for authentication, the service name
+specifies the PAM policy to apply.
+This usually corresponds to an entry in the
+.Pa pam.conf
+file or a file in the
+.Pa /etc/pam.d
+directory.
+The default value is
+.Dq Li sudo .
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It passprompt
+The default prompt to use when asking for a password; can be overridden via the
+.Fl p
+option or the
+.Ev SUDO_PROMPT
+environment variable.
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It Li %H
+expanded to the local host name including the domain name
+(only if the machine's host name is fully qualified or the
+.Em fqdn
+option is set)
+.It Li %h
+expanded to the local host name without the domain name
+.It Li %p
+expanded to the user whose password is being asked for (respects the
+.Em rootpw ,
+.Em targetpw
+and
+.Em runaspw
+flags in
+.Em sudoers )
+.It Li \&%U
+expanded to the login name of the user the command will
+be run as (defaults to root)
+.It Li %u
+expanded to the invoking user's login name
+.It Li %%
+two consecutive
+.Li %
+characters are collapsed into a single
+.Li %
+character
+.El
+.Pp
+On systems that use PAM for authentication,
+.Em passprompt
+will only be used if the prompt provided by the PAM module matches the string
+.Dq "Password: "
+or
+.Dq "username's Password: " .
+This ensures that the
+.Em passprompt
+setting does not interfere with challenge-response style authentication.
+The
+.Em passprompt_override
+flag can be used to change this behavior.
+.Pp
+The default value is
+.Dq Li "@passprompt@" .
+.if \n(PS \{\
+.It privs
+The default Solaris privileges to use when constructing a new
+privilege set for a command.
+This is passed to the executing process via the inherited privilege set,
+but is bounded by the limit privileges.
+If the
+.Em privs
+option is specified but the
+.Em limitprivs
+option is not, the limit privileges of the executing process is set to
+.Em privs .
+The default privileges may be overridden on a per-command basis in
+.Em sudoers .
+This option is only available if
+.Nm
+is built on Solaris 10 or higher.
+.\}
+.if \n(SL \{\
+.It role
+The default SELinux role to use when constructing a new security
+context to run the command.
+The default role may be overridden on a per-command basis in the
+.Em sudoers
+file or via command line options.
+This option is only available when
+.Nm sudo
+is built with SELinux support.
+.\}
+.It runas_default
+The default user to run commands as if the
+.Fl u
+option is not specified on the command line.
+This defaults to
+.Li @runas_default@ .
+.It sudoers_locale
+Locale to use when parsing the sudoers file, logging commands, and
+sending email.
+Note that changing the locale may affect how sudoers is interpreted.
+Defaults to
+.Dq Li C .
+.It timestamp_type
+.Nm
+uses per-user time stamp files for credential caching.
+The
+.Em timestamp_type
+option can be used to specify the type of time stamp record used.
+It has the following possible values:
+.Bl -tag -width 6n
+.It global
+A single time stamp record is used for all of a user's login sessions,
+regardless of the terminal or parent process ID.
+An additional record is used to serialize password prompts when
+.Nm sudo
+is used multiple times in a pipeline, but this does not affect authentication.
+.It ppid
+A single time stamp record is used for all processes with the same parent
+process ID (usually the shell).
+Commands run from the same shell (or other common parent process)
+will not require a password for
+.Em timestamp_timeout
+minutes
+.Po
+.Li @timeout@
+by default
+.Pc .
+Commands run via
+.Nm sudo
+with a different parent process ID, for example from a shell script,
+will be authenticated separately.
+.It tty
+One time stamp record is used for each terminal,
+which means that a user's login sessions are authenticated separately.
+If no terminal is present, the behavior is the same as
+.Em ppid .
+Commands run from the same terminal will not require a password for
+.Em timestamp_timeout
+minutes
+.Po
+.Li @timeout@
+by default
+.Pc .
+.It kernel
+The time stamp is stored in the kernel as an attribute of the terminal
+device.
+If no terminal is present, the behavior is the same as
+.Em ppid .
+Negative
+.Em timestamp_timeout
+values are not supported and positive values are limited to a maximum
+of 60 minutes.
+This is currently only supported on
+.Ox .
+.El
+.Pp
+The default value is
+.Em @timestamp_type@ .
+.Pp
+This setting is only supported by version 1.8.21 or higher.
+.It timestampdir
+The directory in which
+.Nm sudo
+stores its time stamp files.
+This directory should be cleared when the system reboots.
+The default is
+.Pa @rundir@/ts .
+.It timestampowner
+The owner of the lecture status directory, time stamp directory and all
+files stored therein.
+The default is
+.Li root .
+.if \n(SL \{\
+.It type
+The default SELinux type to use when constructing a new security
+context to run the command.
+The default type may be overridden on a per-command basis in the
+.Em sudoers
+file or via command line options.
+This option is only available when
+.Nm sudo
+is built with SELinux support.
+.\}
+.El
+.Pp
+.Sy Strings that can be used in a boolean context :
+.Bl -tag -width 12n
+.It env_file
+The
+.Em env_file
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+.Dq Li VARIABLE=value
+or
+.Dq Li export VARIABLE=value .
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+This file is considered to be part of the security policy,
+its contents are not subject to other
+.Nm sudo
+environment restrictions such as
+.Em env_keep
+and
+.Em env_check .
+.It exempt_group
+Users in this group are exempt from password and PATH requirements.
+The group name specified should not include a
+.Li %
+prefix.
+This is not set by default.
+.It fdexec
+Determines whether
+.Nm sudo
+will execute a command by its path or by an open file descriptor.
+It has the following possible values:
+.Bl -tag -width 6n
+.It always
+Always execute by file descriptor.
+.It never
+Never execute by file descriptor.
+.It digest_only
+Only execute by file descriptor if the command has an associated digest
+in the
+.Em sudoers
+file.
+.El
+.Pp
+The default value is
+.Em digest_only .
+This avoids a time of check versus time of use race condition when
+the command is located in a directory writable by the invoking user.
+.Pp
+Note that
+.Em fdexec
+will change the first element of the argument vector for scripts
+($0 in the shell) due to the way the kernel runs script interpreters.
+Instead of being a normal path, it will refer to a file descriptor.
+For example,
+.Pa /dev/fd/4
+on Solaris and
+.Pa /proc/self/fd/4
+on Linux.
+A workaround is to use the
+.Dv SUDO_COMMAND
+environment variable instead.
+.Pp
+The
+.Em fdexec
+setting is only used when the command is matched by path name.
+It has no effect if the command is matched by the built-in
+.Sy ALL
+alias.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+If the operating system does not support the
+.Xr fexecve 2
+system call, this setting has no effect.
+.It group_plugin
+A string containing a
+.Nm
+group plugin with optional arguments.
+The string should consist of the plugin
+path, either fully-qualified or relative to the
+.Pa @plugindir@
+directory, followed by any configuration arguments the plugin requires.
+These arguments (if any) will be passed to the plugin's initialization function.
+If arguments are present, the string must be enclosed in double quotes
+.Pq \&"" .
+.Pp
+For more information see
+.Sx "GROUP PROVIDER PLUGINS" .
+.It lecture
+This option controls when a short lecture will be printed along with
+the password prompt.
+It has the following possible values:
+.Bl -tag -width 6n
+.It always
+Always lecture the user.
+.It never
+Never lecture the user.
+.It once
+Only lecture the user the first time they run
+.Nm sudo .
+.El
+.Pp
+If no value is specified, a value of
+.Em once
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em @lecture@ .
+.It lecture_file
+Path to a file containing an alternate
+.Nm sudo
+lecture that will be used in place of the standard lecture if the named
+file exists.
+By default,
+.Nm sudo
+uses a built-in lecture.
+.It listpw
+This option controls when a password will be required when a user runs
+.Nm sudo
+with the
+.Fl l
+option.
+It has the following possible values:
+.Bl -tag -width 8n
+.It all
+All the user's
+.Em sudoers
+file entries for the current host must have
+the
+.Li NOPASSWD
+flag set to avoid entering a password.
+.It always
+The user must always enter a password to use the
+.Fl l
+option.
+.It any
+At least one of the user's
+.Em sudoers
+file entries for the current host
+must have the
+.Li NOPASSWD
+flag set to avoid entering a password.
+.It never
+The user need never enter a password to use the
+.Fl l
+option.
+.El
+.Pp
+If no value is specified, a value of
+.Em any
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em any .
+.It log_format
+The event log format.
+Supported log formats are:
+.Bl -tag -width 8n
+.It json
+Logs in JSON format.
+JSON log entries contain the full user details as well as the execution
+environment if the command was allowed.
+Due to limitations of the protocol, JSON events sent via
+.Em syslog
+may be truncated.
+.It sudo
+Traditional sudo-style logs, see
+.Sx "LOG FORMAT"
+for a description of the log file format.
+.El
+.Pp
+This setting affects logs sent via
+.Xr syslog 3
+as well as the file specified by the
+.Em logfile
+setting, if any.
+The default value is
+.Em sudo .
+.It logfile
+Path to the
+.Nm sudo
+log file (not the syslog log file).
+Setting a path turns on logging to a file;
+negating this option turns it off.
+By default,
+.Nm sudo
+logs via syslog.
+.It mailerflags
+Flags to use when invoking mailer.
+Defaults to
+.Fl t .
+.It mailerpath
+Path to mail program used to send warning mail.
+Defaults to the path to sendmail found at configure time.
+.It mailfrom
+Address to use for the
+.Dq from
+address when sending warning and error mail.
+The address should be enclosed in double quotes
+.Pq \&""
+to protect against
+.Nm sudo
+interpreting the
+.Li @
+sign.
+Defaults to the name of the user running
+.Nm sudo .
+.It mailto
+Address to send warning and error mail to.
+The address should be enclosed in double quotes
+.Pq \&""
+to protect against
+.Nm sudo
+interpreting the
+.Li @
+sign.
+Defaults to
+.Li @mailto@ .
+.It restricted_env_file
+The
+.Em restricted_env_file
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+.Dq Li VARIABLE=value
+or
+.Dq Li export VARIABLE=value .
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+Unlike
+.Em env_file ,
+the file's contents are not trusted and are processed in a manner
+similar to that of the invoking user's environment.
+If
+.Em env_reset
+is enabled, variables in the file will only be added if they are
+matched by either the
+.Em env_check
+or
+.Em env_keep
+list.
+If
+.Em env_reset
+is disabled, variables in the file are added as long as they
+are not matched by the
+.Em env_delete
+list.
+In either case, the contents of
+.Em restricted_env_file
+are processed before the contents of
+.Em env_file .
+.It runchroot
+If set,
+.Nm sudo
+will use this value for the root directory when running a command.
+The special value
+.Dq *
+will allow the user to specify the root directory via
+.Nm sudo Ns 's
+.Fl R
+option.
+See the
+.Sx Chroot_Spec
+section for more details.
+.Pp
+It is only possible to use
+.Em runchroot
+as a command-specific Defaults setting if the command exists with
+the same path both inside and outside the chroot jail.
+This restriction does not apply to generic, host or user-based
+Defaults settings or to a
+.Em Cmnd_Spec
+that includes a
+.Em Chroot_Spec .
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.It runcwd
+If set,
+.Nm sudo
+will use this value for the working directory when running a command.
+The special value
+.Dq *
+will allow the user to specify the working directory via
+.Nm sudo Ns 's
+.Fl D
+option.
+See the
+.Sx Chdir_Spec
+section for more details.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.It secure_path
+If set,
+.Nm sudo
+will use this value in place of the user's
+.Ev PATH
+environment variable.
+This option can be used to reset the
+.Ev PATH
+to a known good value that contains directories for system administrator
+commands such as
+.Pa /usr/sbin .
+.Pp
+Users in the group specified by the
+.Em exempt_group
+option are not affected by
+.Em secure_path .
+This option is @secure_path@ by default.
+.It syslog
+Syslog facility if syslog is being used for logging (negate to
+disable syslog logging).
+Defaults to
+.Li @logfac@ .
+.Pp
+The following syslog facilities are supported:
+.Sy authpriv
+(if your
+OS supports it),
+.Sy auth ,
+.Sy daemon ,
+.Sy user ,
+.Sy local0 ,
+.Sy local1 ,
+.Sy local2 ,
+.Sy local3 ,
+.Sy local4 ,
+.Sy local5 ,
+.Sy local6 ,
+and
+.Sy local7 .
+.It syslog_badpri
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to
+.Li @badpri@ .
+.Pp
+The following syslog priorities are supported:
+.Sy alert ,
+.Sy crit ,
+.Sy debug ,
+.Sy emerg ,
+.Sy err ,
+.Sy info ,
+.Sy notice ,
+.Sy warning ,
+and
+.Sy none .
+Negating the option or setting it to a value of
+.Sy none
+will disable logging of unsuccessful commands.
+.It syslog_goodpri
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to
+.Li @goodpri@ .
+.Pp
+See
+.Em syslog_badpri
+for the list of supported syslog priorities.
+Negating the option or setting it to a value of
+.Sy none
+will disable logging of successful commands.
+.It verifypw
+This option controls when a password will be required when a user runs
+.Nm sudo
+with the
+.Fl v
+option.
+It has the following possible values:
+.Bl -tag -width 6n
+.It all
+All the user's
+.Em sudoers
+file entries for the current host must have the
+.Li NOPASSWD
+flag set to avoid entering a password.
+.It always
+The user must always enter a password to use the
+.Fl v
+option.
+.It any
+At least one of the user's
+.Em sudoers
+file entries for the current host must have the
+.Li NOPASSWD
+flag set to avoid entering a password.
+.It never
+The user need never enter a password to use the
+.Fl v
+option.
+.El
+.Pp
+If no value is specified, a value of
+.Em all
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em all .
+.El
+.Pp
+.Sy Lists that can be used in a boolean context :
+.Bl -tag -width 16n
+.It env_check
+Environment variables to be removed from the user's environment
+unless they are considered
+.Dq safe .
+For all variables except
+.Li TZ ,
+.Dq safe
+means that the variable's value does not contain any
+.Ql %
+or
+.Ql /
+characters.
+This can be used to guard against printf-style format vulnerabilities
+in poorly-written programs.
+The
+.Li TZ
+variable is considered unsafe if any of the following are true:
+.Bl -bullet -width 1n
+.It
+It consists of a fully-qualified path name,
+optionally prefixed with a colon
+.Pq Ql :\& ,
+that does not match the location of the
+.Pa zoneinfo
+directory.
+.It
+It contains a
+.Pa ..
+path element.
+.It
+It contains white space or non-printable characters.
+.It
+It is longer than the value of
+.Li PATH_MAX .
+.El
+.Pp
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using
+the
+.Li = ,
+.Li += ,
+.Li -= ,
+and
+.Li \&!
+operators respectively.
+Regardless of whether the
+.Li env_reset
+option is enabled or disabled, variables specified by
+.Li env_check
+will be preserved in the environment if they pass the aforementioned check.
+The global list of environment variables to check is displayed when
+.Nm sudo
+is run by root with
+the
+.Fl V
+option.
+.It env_delete
+Environment variables to be removed from the user's environment when the
+.Em env_reset
+option is not in effect.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+.Li = ,
+.Li += ,
+.Li -= ,
+and
+.Li \&!
+operators respectively.
+The global list of environment variables to remove is displayed when
+.Nm sudo
+is run by root with the
+.Fl V
+option.
+Note that many operating systems will remove potentially dangerous
+variables from the environment of any set-user-ID process (such as
+.Nm sudo ) .
+.It env_keep
+Environment variables to be preserved in the user's environment when the
+.Em env_reset
+option is in effect.
+This allows fine-grained control over the environment
+.Nm sudo Ns -spawned
+processes will receive.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+.Li = ,
+.Li += ,
+.Li -= ,
+and
+.Li \&!
+operators respectively.
+The global list of variables to keep
+is displayed when
+.Nm sudo
+is run by root with the
+.Fl V
+option.
+.Pp
+Preserving the
+.Ev HOME
+environment variable has security implications since many programs use it
+when searching for configuration or data files.
+Adding
+.Ev HOME
+to
+.Em env_keep
+may enable a user to run unrestricted commands via
+.Nm sudo
+and is strongly discouraged.
+Users wishing to edit files with
+.Nm sudo
+should run
+.Nm sudoedit
+(or
+.Nm sudo Fl e )
+to get their accustomed editor configuration instead of
+invoking the editor directly.
+.It log_servers
+A list of one or more servers to use for remote event and I/O log storage,
+separated by white space.
+Log servers must be running
+.Nm sudo_logsrvd
+or another service that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Pp
+Server addresses should be of the form
+.Dq host Ns Oo : Ns port Oc Ns Op (tls) .
+The host portion may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+.Pp
+If the optional
+.Em tls
+flag is present, the connection will be secured
+with Transport Layer Security (TLS) version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+.Pp
+If a port is specified, it may either be a port number or a well-known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.Pp
+When
+.Em log_servers
+is set, event log data will be logged both locally (see the
+.Em syslog
+and
+.Em log_file
+settings) as well as remotely, but I/O log data will only be logged remotely.
+If multiple hosts are specified, they will be attempted in reverse order.
+If no log servers are available, the user will not be able to run
+a command unless either the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+Likewise, if the connection to the log server is interrupted while
+.Nm sudo
+is running, the command will be terminated unless the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.El
+.Sh GROUP PROVIDER PLUGINS
+The
+.Nm
+plugin supports its own plugin interface to allow non-Unix
+group lookups which can query a group source other
+than the standard Unix group database.
+This can be used to implement support for the
+.Li nonunix_group
+syntax described earlier.
+.Pp
+Group provider plugins are specified via the
+.Em group_plugin
+setting.
+The argument to
+.Em group_plugin
+should consist of the plugin path, either fully-qualified or relative to the
+.Pa @plugindir@
+directory, followed by any configuration options the plugin requires.
+These options (if specified) will be passed to the plugin's initialization
+function.
+If options are present, the string must be enclosed in double quotes
+.Pq \&"" .
+.Pp
+The following group provider plugins are installed by default:
+.Bl -tag -width 8n
+.It group_file
+The
+.Em group_file
+plugin supports an alternate group file that uses the same syntax as the
+.Pa /etc/group
+file.
+The path to the group file should be specified as an option
+to the plugin.
+For example, if the group file to be used is
+.Pa /etc/sudo-group :
+.Bd -literal
+Defaults group_plugin="group_file.so /etc/sudo-group"
+.Ed
+.It system_group
+The
+.Em system_group
+plugin supports group lookups via the standard C library functions
+.Fn getgrnam
+and
+.Fn getgrid .
+This plugin can be used in instances where the user belongs to
+groups not present in the user's supplemental group vector.
+This plugin takes no options:
+.Bd -literal
+Defaults group_plugin=system_group.so
+.Ed
+.El
+.Pp
+The group provider plugin API is described in detail in
+.Xr sudo_plugin @mansectform@ .
+.Sh LOG FORMAT
+.Nm
+can log events in either JSON or
+.Em sudo
+format,
+this section describes the
+.Em sudo
+log format.
+Depending on
+.Em sudoers
+configuration,
+.Nm
+can log events via
+.Xr syslog 3 ,
+to a local log file, or both.
+The log format is almost identical in both cases.
+.Ss Accepted command log entries
+Commands that sudo runs are logged using the following format (split
+into multiple lines for readability):
+.Bd -literal -offset 4n
+date hostname progname: username : TTY=ttyname ; PWD=cwd ; \e
+ USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
+ ENV=env_vars COMMAND=command
+.Ed
+.Pp
+Where the fields are as follows:
+.Bl -tag -width 12n
+.It date
+The date the command was run.
+Typically, this is in the format
+.Dq MMM, DD, HH:MM:SS .
+If logging via
+.Xr syslog 3 ,
+the actual date format is controlled by the syslog daemon.
+If logging to a file and the
+.Em log_year
+option is enabled,
+the date will also include the year.
+.It hostname
+The name of the host
+.Nm sudo
+was run on.
+This field is only present when logging via
+.Xr syslog 3 .
+.It progname
+The name of the program, usually
+.Em sudo
+or
+.Em sudoedit .
+This field is only present when logging via
+.Xr syslog 3 .
+.It username
+The login name of the user who ran
+.Nm sudo .
+.It ttyname
+The short name of the terminal (e.g.,
+.Dq console ,
+.Dq tty01 ,
+or
+.Dq pts/0 )
+.Nm sudo
+was run on, or
+.Dq unknown
+if there was no terminal present.
+.It cwd
+The current working directory that
+.Nm sudo
+was run in.
+.It runasuser
+The user the command was run as.
+.It runasgroup
+The group the command was run as if one was specified on the command line.
+.It logid
+An I/O log identifier that can be used to replay the command's output.
+This is only present when the
+.Em log_input
+or
+.Em log_output
+option is enabled.
+.It env_vars
+A list of environment variables specified on the command line,
+if specified.
+.It command
+The actual command that was executed.
+.El
+.Pp
+Messages are logged using the locale specified by
+.Em sudoers_locale ,
+which defaults to the
+.Dq Li C
+locale.
+.Ss Denied command log entries
+If the user is not allowed to run the command, the reason for the denial
+will follow the user name.
+Possible reasons include:
+.Bl -tag -width 4
+.It user NOT in sudoers
+The user is not listed in the
+.Em sudoers
+file.
+.It user NOT authorized on host
+The user is listed in the
+.Em sudoers
+file but is not allowed to run commands on the host.
+.It command not allowed
+The user is listed in the
+.Em sudoers
+file for the host but they are not allowed to run the specified command.
+.It 3 incorrect password attempts
+The user failed to enter their password after 3 tries.
+The actual number of tries will vary based on the number of
+failed attempts and the value of the
+.Em passwd_tries
+option.
+.It a password is required
+The
+.Fl n
+option was specified but a password was required.
+.It sorry, you are not allowed to set the following environment variables
+The user specified environment variables on the command line that
+were not allowed by
+.Em sudoers .
+.El
+.Ss Error log entries
+If an error occurs,
+.Nm
+will log a message and, in most cases, send a message to the
+administrator via email.
+Possible errors include:
+.Bl -tag -width 4
+.It parse error in @sysconfdir@/sudoers near line N
+.Nm
+encountered an error when parsing the specified file.
+In some cases, the actual error may be one line above or below the
+line number listed, depending on the type of error.
+.It problem with defaults entries
+The
+.Em sudoers
+file contains one or more unknown Defaults settings.
+This does not prevent
+.Nm sudo
+from running, but the
+.Em sudoers
+file should be checked using
+.Nm visudo .
+.It timestamp owner (username): \&No such user
+The time stamp directory owner, as specified by the
+.Em timestampowner
+setting, could not be found in the password database.
+.It unable to open/read @sysconfdir@/sudoers
+The
+.Em sudoers
+file could not be opened for reading.
+This can happen when the
+.Em sudoers
+file is located on a remote file system that maps user-ID 0 to
+a different value.
+Normally,
+.Nm
+tries to open the
+.Em sudoers
+file using group permissions to avoid this problem.
+Consider either changing the ownership of
+.Pa @sysconfdir@/sudoers
+or adding an argument like
+.Dq sudoers_uid=N
+(where
+.Sq N
+is the user-ID that owns the
+.Em sudoers
+file) to the end of the
+.Nm
+.Li Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It unable to stat @sysconfdir@/sudoers
+The
+.Pa @sysconfdir@/sudoers
+file is missing.
+.It @sysconfdir@/sudoers is not a regular file
+The
+.Pa @sysconfdir@/sudoers
+file exists but is not a regular file or symbolic link.
+.It @sysconfdir@/sudoers is owned by uid N, should be 0
+The
+.Em sudoers
+file has the wrong owner.
+If you wish to change the
+.Em sudoers
+file owner, please add
+.Dq sudoers_uid=N
+(where
+.Sq N
+is the user-ID that owns the
+.Em sudoers
+file) to the
+.Nm
+.Li Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It @sysconfdir@/sudoers is world writable
+The permissions on the
+.Em sudoers
+file allow all users to write to it.
+The
+.Em sudoers
+file must not be world-writable, the default file mode
+is 0440 (readable by owner and group, writable by none).
+The default mode may be changed via the
+.Dq sudoers_mode
+option to the
+.Nm
+.Li Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It @sysconfdir@/sudoers is owned by gid N, should be 1
+The
+.Em sudoers
+file has the wrong group ownership.
+If you wish to change the
+.Em sudoers
+file group ownership, please add
+.Dq sudoers_gid=N
+(where
+.Sq N
+is the group-ID that owns the
+.Em sudoers
+file) to the
+.Nm
+.Li Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It unable to open @rundir@/ts/username
+.Nm
+was unable to read or create the user's time stamp file.
+This can happen when
+.Em timestampowner
+is set to a user other than root and the mode on
+.Pa @rundir@
+is not searchable by group or other.
+The default mode for
+.Pa @rundir@
+is 0711.
+.It unable to write to @rundir@/ts/username
+.Nm
+was unable to write to the user's time stamp file.
+.It @rundir@/ts is owned by uid X, should be Y
+The time stamp directory is owned by a user other than
+.Em timestampowner .
+This can occur when the value of
+.Em timestampowner
+has been changed.
+.Nm
+will ignore the time stamp directory until the owner is corrected.
+.It @rundir@/ts is group writable
+The time stamp directory is group-writable; it should be writable only by
+.Em timestampowner .
+The default mode for the time stamp directory is 0700.
+.Nm
+will ignore the time stamp directory until the mode is corrected.
+.El
+.Ss Notes on logging via syslog
+By default,
+.Nm
+logs messages via
+.Xr syslog 3 .
+The
+.Em date ,
+.Em hostname ,
+and
+.Em progname
+fields are added by the system's
+.Fn syslog
+function, not
+.Nm
+itself.
+As such, they may vary in format on different systems.
+.Pp
+The maximum size of syslog messages varies from system to system.
+The
+.Em syslog_maxlen
+setting can be used to change the maximum syslog message size
+from the default value of 980 bytes.
+For more information, see the description of
+.Em syslog_maxlen .
+.Ss Notes on logging to a file
+If the
+.Em logfile
+option is set,
+.Nm
+will log to a local file, such as
+.Pa /var/log/sudo .
+When logging to a file,
+.Nm
+uses a format similar to
+.Xr syslog 3 ,
+with a few important differences:
+.Bl -enum
+.It
+The
+.Em progname
+and
+.Em hostname
+fields are not present.
+.It
+If the
+.Em log_year
+option is enabled,
+the date will also include the year.
+.It
+Lines that are longer than
+.Em loglinelen
+characters (80 by default) are word-wrapped and continued on the
+next line with a four character indent.
+This makes entries easier to read for a human being, but makes it
+more difficult to use
+.Xr grep 1
+on the log files.
+If the
+.Em loglinelen
+option is set to 0 (or negated with a
+.Ql \&! ) ,
+word wrap will be disabled.
+.El
+.Sh I/O LOG FILES
+When I/O logging is enabled,
+.Nm sudo
+will run the command in a pseudo-terminal and log all user input and/or output,
+depending on which options are enabled.
+I/O can be logged either to the local machine or to a remote log server.
+For local logs, I/O is logged to the directory specified by the
+.Em iolog_dir
+option
+.Po
+.Pa @iolog_dir@
+by default
+.Pc
+using a unique session ID that is included in the
+.Nm sudo
+log line, prefixed with
+.Dq Li TSID= .
+The
+.Em iolog_file
+option may be used to control the format of the session ID.
+For remote logs, the
+.Em log_servers
+setting is used to specify one or more log servers running
+.Nm sudo_logsrvd
+or another server that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Pp
+For both local and remote I/O logs, each log is stored in a separate
+directory that contains the following files:
+.Bl -tag -width 8n
+.It Pa log
+A text file containing information about the command.
+The first line consists of the following colon-delimited fields:
+the time the command was run, the name of the user
+who ran
+.Nm sudo ,
+the name of the target user, the name of the target group (optional),
+the terminal that
+.Nm sudo
+was run from, and the number of lines and columns of the terminal.
+The second and third lines contain the working directory the command
+was run from and the path name of the command itself (with arguments
+if present).
+.It Pa log.json
+A JSON-formatted file containing information about the command.
+This is similar to the
+.Pa log
+file but contains additional information and is easily extensible.
+The
+.Pa log.json
+file will be used by
+.Xr sudoreplay @mansectsu@
+in preference to the
+.Pa log
+file if it exists.
+The file may contain the following elements:
+.Bl -tag -width 8n
+.It timestamp
+A JSON object containing time the command was run.
+It consists of two values,
+.Em seconds
+and
+.Em nanoseconds .
+.It columns
+The number of columns of the terminal the command ran on, or zero
+if no terminal was present.
+.It command
+The fully-qualified path of the command that was run.
+.It lines
+The number of lines of the terminal the command ran on, or zero
+if no terminal was present.
+.It runargv
+A JSON array representing the command's argument vector as passed to the
+.Xr execve 2
+system call.
+.It runenv
+A JSON array representing the command's environment as passed to the
+.Xr execve 2
+system call.
+.It rungid
+The group ID the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.It rungroup
+The name of the group the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.It runuid
+The user ID the command ran as.
+.It runuser
+The name of the user the command ran as.
+.It submitcwd
+The current working directory at the time
+.Nm sudo
+was run.
+.It submithost
+The name of the host the command was run on.
+.It submituser
+The name of the user who ran the command via
+.Nm sudo .
+.It ttyname
+The path name of the terminal the user invoked
+.Nm sudo
+from.
+If the command was run in a pseudo-terminal,
+.Em ttyname
+will be different from the terminal the command actually ran in.
+.El
+.It Pa timing
+Timing information used to replay the session.
+Each line consists of the I/O log entry type and amount of time
+since the last entry, followed by type-specific data.
+The I/O log entry types and their corresponding type-specific data are:
+.Pp
+.Bl -tag -width 4n -compact
+.It 0
+standard input, number of bytes in the entry
+.It 1
+standard output, number of bytes in the entry
+.It 2
+standard error, number of bytes in the entry
+.It 3
+terminal input, number of bytes in the entry
+.It 4
+terminal output, number of bytes in the entry
+.It 5
+window change, new number lines and columns
+.It 6
+bug compatibility for
+.Nm sudo
+1.8.7 terminal output
+.It 7
+command suspend or resume, signal received
+.El
+.It Pa ttyin
+Raw input from the user's terminal, exactly as it was received.
+No post-processing is performed.
+For manual viewing, you may wish to convert carriage return characters
+in the log to line feeds.
+For example:
+.Ql gunzip -c ttyin | tr \&"\er\&" \&"\en\&"
+.It Pa stdin
+The standard input when no terminal is present, or input redirected from
+a pipe or file.
+.It Pa ttyout
+Output from the pseudo-terminal (what the command writes to the screen).
+Note that terminal-specific post-processing is performed before the
+data is logged.
+This means that, for example, line feeds are usually converted to
+line feed/carriage return pairs and tabs may be expanded to spaces.
+.It Pa stdout
+The standard output when no terminal is present, or output redirected to
+a pipe or file.
+.It Pa stderr
+The standard error redirected to a pipe or file.
+.El
+.Pp
+All files other than
+.Pa log
+are compressed in gzip format unless the
+.Em compress_io
+flag has been disabled.
+Due to buffering, it is not normally possible to display the I/O logs in
+real-time as the program is executing.
+The I/O log data will not be complete until the program run by
+.Nm sudo
+has exited or has been terminated by a signal.
+The
+.Em iolog_flush
+flag can be used to disable buffering, in which case I/O log data
+is written to disk as soon as it is available.
+The output portion of an I/O log file can be viewed with the
+.Xr sudoreplay @mansectsu@
+utility, which can also be used to list or search the available logs.
+.Pp
+Note that user input may contain sensitive information such as
+passwords (even if they are not echoed to the screen), which will
+be stored in the log file unencrypted.
+In most cases, logging the command output via
+.Em log_output
+or
+.Li LOG_OUTPUT
+is all that is required.
+.Pp
+Since each session's I/O logs are stored in a separate directory,
+traditional log rotation utilities cannot be used to limit the
+number of I/O logs.
+The simplest way to limit the number of I/O is by setting the
+.Em maxseq
+option to the maximum number of logs you wish to store.
+Once the I/O log sequence number reaches
+.Em maxseq ,
+it will be reset to zero and
+.Nm
+will truncate and re-use any existing I/O logs.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front end configuration
+.It Pa @sysconfdir@/sudoers
+List of who can run what
+.It Pa /etc/group
+Local groups file
+.It Pa /etc/netgroup
+List of network groups
+.It Pa @iolog_dir@
+I/O log files
+.It Pa @rundir@/ts
+Directory containing time stamps for the
+.Nm
+security policy
+.It Pa @vardir@/lectured
+Directory containing lecture status files for the
+.Nm
+security policy
+.It Pa /etc/environment
+Initial environment for
+.Fl i
+mode on AIX and Linux systems
+.El
+.Sh EXAMPLES
+Below are example
+.Em sudoers
+file entries.
+Admittedly, some of these are a bit contrived.
+First, we allow a few environment variables to pass and then define our
+.Em aliases :
+.Bd -literal
+# Run X applications through sudo; HOME is used to find the
+# .Xauthority file. Note that other programs use HOME to find
+# configuration files and this may lead to privilege escalation!
+Defaults env_keep += "DISPLAY HOME"
+
+# User alias specification
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+# Runas alias specification
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+Runas_Alias ADMINGRP = adm, oper
+
+# Host alias specification
+Host_Alias SPARC = bigtime, eclipse, moet, anchor :\e
+ SGI = grolsch, dandelion, black :\e
+ ALPHA = widget, thalamus, foobar :\e
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+# Cmnd alias specification
+Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e
+ /usr/sbin/restore, /usr/sbin/rrestore,\e
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh,\e
+ /usr/local/bin/tcsh, /usr/bin/rsh,\e
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+.Ed
+.Pp
+Here we override some of the compiled in default values.
+We want
+.Nm sudo
+to log via
+.Xr syslog 3
+using the
+.Em auth
+facility in all cases and for commands to be run with
+the target user's home directory as the working directory.
+We don't want to subject the full time staff to the
+.Nm sudo
+lecture and we want to allow them to run commands in a
+.Xr chroot 2
+.Dq sandbox
+via the
+.Fl R
+option.
+User
+.Sy millert
+need not provide a password and we don't want to reset the
+.Ev LOGNAME
+or
+.Ev USER
+environment variables when running commands as root.
+Additionally, on the machines in the
+.Em SERVERS
+.Li Host_Alias ,
+we keep an additional local log file and make sure we log the year
+in each log line since the log entries will be kept around for several years.
+Lastly, we disable shell escapes for the commands in the PAGERS
+.Li Cmnd_Alias
+.Po
+.Pa /usr/bin/more ,
+.Pa /usr/bin/pg
+and
+.Pa /usr/bin/less
+.Pc .
+Note that this will not effectively constrain users with
+.Nm sudo
+.Sy ALL
+privileges.
+.Bd -literal
+# Override built-in defaults
+Defaults syslog=auth,runcwd=~
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture,runchroot=*
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+.Ed
+.Pp
+The
+.Em User specification
+is the part that actually determines who may run what.
+.Bd -literal
+root ALL = (ALL) ALL
+%wheel ALL = (ALL) ALL
+.Ed
+.Pp
+We let
+.Sy root
+and any user in group
+.Sy wheel
+run any command on any host as any user.
+.Bd -literal
+FULLTIMERS ALL = NOPASSWD: ALL
+.Ed
+.Pp
+Full time sysadmins
+.Po
+.Sy millert ,
+.Sy mikef ,
+and
+.Sy dowdy
+.Pc
+may run any command on any host without authenticating themselves.
+.Bd -literal
+PARTTIMERS ALL = ALL
+.Ed
+.Pp
+Part time sysadmins
+.Sy bostley ,
+.Sy jwfox ,
+and
+.Sy crawl )
+may run any command on any host but they must authenticate themselves
+first (since the entry lacks the
+.Li NOPASSWD
+tag).
+.Bd -literal
+jack CSNETS = ALL
+.Ed
+.Pp
+The user
+.Sy jack
+may run any command on the machines in the
+.Em CSNETS
+alias (the networks
+.Li 128.138.243.0 ,
+.Li 128.138.204.0 ,
+and
+.Li 128.138.242.0 ) .
+Of those networks, only
+.Li 128.138.204.0
+has an explicit netmask (in CIDR notation) indicating it is a class C network.
+For the other networks in
+.Em CSNETS ,
+the local machine's netmask will be used during matching.
+.Bd -literal
+lisa CUNETS = ALL
+.Ed
+.Pp
+The user
+.Sy lisa
+may run any command on any host in the
+.Em CUNETS
+alias (the class B network
+.Li 128.138.0.0 ) .
+.Bd -literal
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\e
+ sudoedit /etc/printcap, /usr/oper/bin/
+.Ed
+.Pp
+The
+.Sy operator
+user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory
+.Pa /usr/oper/bin/ .
+Note that one command in the
+.Li DUMPS
+Cmnd_Alias includes a sha224 digest,
+.Pa /home/operator/bin/start_backups .
+This is because the directory containing the script is writable by the
+operator user.
+If the script is modified (resulting in a digest mismatch) it will no longer
+be possible to run it via
+.Nm sudo .
+.Bd -literal
+joe ALL = /usr/bin/su operator
+.Ed
+.Pp
+The user
+.Sy joe
+may only
+.Xr su 1
+to operator.
+.Bd -literal
+pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root*
+
+%opers ALL = (: ADMINGRP) /usr/sbin/
+.Ed
+.Pp
+Users in the
+.Sy opers
+group may run commands in
+.Pa /usr/sbin/
+as themselves
+with any group in the
+.Em ADMINGRP
+.Li Runas_Alias
+(the
+.Sy adm
+and
+.Sy oper
+groups).
+.Pp
+The user
+.Sy pete
+is allowed to change anyone's password except for
+root on the
+.Em HPPA
+machines.
+Because command line arguments are matched as a single,
+concatenated string, the
+.Ql *
+wildcard will match
+.Em multiple
+words.
+This example assumes that
+.Xr passwd 1
+does not take multiple user names on the command line.
+Note that on GNU systems, options to
+.Xr passwd 1
+may be specified after the user argument.
+As a result, this rule will also allow:
+.Bd -literal -offset 4n
+passwd username --expire
+.Ed
+.Pp
+which may not be desirable.
+.Bd -literal
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+.Ed
+.Pp
+The user
+.Sy bob
+may run anything on the
+.Em SPARC
+and
+.Em SGI
+machines as any user listed in the
+.Em OP
+.Li Runas_Alias
+.Po
+.Sy root
+and
+.Sy operator .
+.Pc
+.Bd -literal
+jim +biglab = ALL
+.Ed
+.Pp
+The user
+.Sy jim
+may run any command on machines in the
+.Em biglab
+netgroup.
+.Nm sudo
+knows that
+.Dq biglab
+is a netgroup due to the
+.Ql +
+prefix.
+.Bd -literal
++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+.Ed
+.Pp
+Users in the
+.Sy secretaries
+netgroup need to help manage the printers as well as add and remove users,
+so they are allowed to run those commands on all machines.
+.Bd -literal
+fred ALL = (DB) NOPASSWD: ALL
+.Ed
+.Pp
+The user
+.Sy fred
+can run commands as any user in the
+.Em DB
+.Li Runas_Alias
+.Po
+.Sy oracle
+or
+.Sy sybase
+.Pc
+without giving a password.
+.Bd -literal
+john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+.Ed
+.Pp
+On the
+.Em ALPHA
+machines, user
+.Sy john
+may su to anyone except root but he is not allowed to specify any options
+to the
+.Xr su 1
+command.
+.Bd -literal
+jen ALL, !SERVERS = ALL
+.Ed
+.Pp
+The user
+.Sy jen
+may run any command on any machine except for those in the
+.Em SERVERS
+.Li Host_Alias
+(primary, mail, www and ns).
+.Bd -literal
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+.Ed
+.Pp
+For any machine in the
+.Em SERVERS
+.Li Host_Alias ,
+.Sy jill
+may run
+any commands in the directory
+.Pa /usr/bin/
+except for those commands
+belonging to the
+.Em SU
+and
+.Em SHELLS
+.Li Cmnd_Aliases .
+While not specifically mentioned in the rule, the commands in the
+.Em PAGERS
+.Li Cmnd_Alias
+all reside in
+.Pa /usr/bin
+and have the
+.Em noexec
+option set.
+.Bd -literal
+steve CSNETS = (operator) /usr/local/op_commands/
+.Ed
+.Pp
+The user
+.Sy steve
+may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+.Bd -literal
+matt valkyrie = KILL
+.Ed
+.Pp
+On his personal workstation, valkyrie,
+.Sy matt
+needs to be able to kill hung processes.
+.Bd -literal
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+.Ed
+.Pp
+On the host www, any user in the
+.Em WEBADMIN
+.Li User_Alias
+(will, wendy, and wim), may run any command as user www (which owns the
+web pages) or simply
+.Xr su 1
+to www.
+.Bd -literal
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\e
+ /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM
+.Ed
+.Pp
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+.Li Host_Alias
+(orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candidate
+for encapsulating in a shell script.
+.Sh SECURITY NOTES
+.Ss Limitations of the So !\& Sc operator
+It is generally not effective to
+.Dq subtract
+commands from
+.Sy ALL
+using the
+.Ql !\&
+operator.
+A user can trivially circumvent this by copying the desired command
+to a different name and then executing that.
+For example:
+.Bd -literal
+bill ALL = ALL, !SU, !SHELLS
+.Ed
+.Pp
+Doesn't really prevent
+.Sy bill
+from running the commands listed in
+.Em SU
+or
+.Em SHELLS
+since he can simply copy those commands to a different name, or use
+a shell escape from an editor or other program.
+Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
+.Pp
+In general, if a user has sudo
+.Sy ALL
+there is nothing to prevent them from creating their own program that gives
+them a root shell (or making their own copy of a shell) regardless of any
+.Ql !\&
+elements in the user specification.
+.Ss Security implications of Em fast_glob
+If the
+.Em fast_glob
+option is in use, it is not possible to reliably negate commands where the
+path name includes globbing (aka wildcard) characters.
+This is because the C library's
+.Xr fnmatch 3
+function cannot resolve relative paths.
+While this is typically only an inconvenience for rules that grant privileges,
+it can result in a security issue for rules that subtract or revoke privileges.
+.Pp
+For example, given the following
+.Em sudoers
+file entry:
+.Bd -literal
+john ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\e
+ /usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
+.Ed
+.Pp
+User
+.Sy john
+can still run
+.Li /usr/bin/passwd root
+if
+.Em fast_glob
+is enabled by changing to
+.Pa /usr/bin
+and running
+.Li ./passwd root
+instead.
+.Ss Preventing shell escapes
+Once
+.Nm sudo
+executes a program, that program is free to do whatever
+it pleases, including run other programs.
+This can be a security issue since it is not uncommon for a program to
+allow shell escapes, which lets a user bypass
+.Nm sudo Ns 's
+access control and logging.
+Common programs that permit shell escapes include shells (obviously),
+editors, paginators, mail and terminal programs.
+.Pp
+There are two basic approaches to this problem:
+.Bl -tag -width 8n
+.It restrict
+Avoid giving users access to commands that allow the user to run
+arbitrary commands.
+Many editors have a restricted mode where shell
+escapes are disabled, though
+.Nm sudoedit
+is a better solution to
+running editors via
+.Nm sudo .
+Due to the large number of programs that
+offer shell escapes, restricting users to the set of programs that
+do not is often unworkable.
+.It noexec
+Many systems that support shared libraries have the ability to
+override default library functions by pointing an environment
+variable (usually
+.Ev LD_PRELOAD )
+to an alternate shared library.
+On such systems,
+.Nm sudo Ns 's
+.Em noexec
+functionality can be used to prevent a program run by
+.Nm sudo
+from executing any other programs.
+Note, however, that this applies only to dynamically-linked
+executables.
+Statically-linked executables and executables
+running under binary emulation are not affected.
+.Pp
+The
+.Em noexec
+feature is known to work on SunOS, Solaris, *BSD,
+Linux, IRIX, Tru64 UNIX, macOS, HP-UX 11.x and AIX 5.3 and above.
+It should be supported on most operating systems that support the
+.Ev LD_PRELOAD
+environment variable.
+Check your operating system's manual pages for the dynamic linker
+(usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to see if
+.Ev LD_PRELOAD
+is supported.
+.Pp
+On Solaris 10 and higher,
+.Em noexec
+uses Solaris privileges instead of the
+.Ev LD_PRELOAD
+environment variable.
+.Pp
+To enable
+.Em noexec
+for a command, use the
+.Li NOEXEC
+tag as documented
+in the User Specification section above.
+Here is that example again:
+.Bd -literal
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.Ed
+.Pp
+This allows user
+.Sy aaron
+to run
+.Pa /usr/bin/more
+and
+.Pa /usr/bin/vi
+with
+.Em noexec
+enabled.
+This will prevent those two commands from
+executing other commands (such as a shell).
+If you are unsure whether or not your system is capable of supporting
+.Em noexec
+you can always just try it out and check whether shell escapes work when
+.Em noexec
+is enabled.
+.El
+.Pp
+Note that restricting shell escapes is not a panacea.
+Programs running as root are still capable of many potentially hazardous
+operations (such as changing or overwriting files) that could lead
+to unintended privilege escalation.
+In the specific case of an editor, a safer approach is to give the
+user permission to run
+.Nm sudoedit
+(see below).
+.Ss Secure editing
+The
+.Nm
+plugin includes
+.Nm sudoedit
+support which allows users to securely edit files with the editor
+of their choice.
+As
+.Nm sudoedit
+is a built-in command, it must be specified in the
+.Em sudoers
+file without a leading path.
+However, it may take command line arguments just as a normal command does.
+Wildcards used in
+.Em sudoedit
+command line arguments are expected to be path names, so a forward slash
+.Pq Ql /
+will not be matched by a wildcard.
+.Pp
+Unlike other
+.Nm sudo
+commands, the editor is run with the permissions of the invoking
+user and with the environment unmodified.
+More information may be found in the description of the
+.Fl e
+option in
+.Xr sudo @mansectsu@ .
+.Pp
+For example, to allow user operator to edit the
+.Dq message of the day
+file:
+.Bd -literal -offset indent
+operator sudoedit /etc/motd
+.Ed
+.Pp
+The operator user then runs
+.Nm sudoedit
+as follows:
+.Bd -literal -offset indent
+$ sudoedit /etc/motd
+.Ed
+.Pp
+The editor will run as the operator user, not root, on a temporary copy of
+.Pa /etc/motd .
+After the file has been edited,
+.Pa /etc/motd
+will be updated with the contents of the temporary copy.
+.Pp
+Users should
+.Em never
+be granted
+.Nm sudoedit
+permission to edit a file that resides in a directory the user
+has write access to, either directly or via a wildcard.
+If the user has write access to the directory it is possible to
+replace the legitimate file with a link to another file,
+allowing the editing of arbitrary files.
+To prevent this, starting with version 1.8.16, symbolic links will
+not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory
+unless the
+.Em sudoedit_checkdir
+option has been disabled or the invoking user is root.
+Additionally, in version 1.8.15 and higher,
+.Nm sudoedit
+will refuse to open a symbolic link unless either the
+.Em sudoedit_follow
+option is enabled or the
+.Em sudoedit
+command is prefixed with the
+.Li FOLLOW
+tag in the
+.Em sudoers
+file.
+.Ss Time stamp file checks
+.Nm
+will check the ownership of its time stamp directory
+.Po
+.Pa @rundir@/ts
+by default
+.Pc
+and ignore the directory's contents if it is not owned by root or
+if it is writable by a user other than root.
+Older versions of
+.Nm sudo
+stored time stamp files in
+.Pa /tmp ;
+this is no longer recommended as it may be possible for a user
+to create the time stamp themselves on systems that allow
+unprivileged users to change the ownership of files they create.
+.Pp
+While the time stamp directory
+.Em should
+be cleared at reboot time, not all systems contain a
+.Pa /run
+or
+.Pa /var/run
+directory.
+To avoid potential problems,
+.Nm
+will ignore time stamp files that date from before the machine booted
+on systems where the boot time is available.
+.Pp
+Some systems with graphical desktop environments allow unprivileged
+users to change the system clock.
+Since
+.Nm
+relies on the system clock for time stamp validation, it may be
+possible on such systems for a user to run
+.Nm sudo
+for longer than
+.Em timestamp_timeout
+by setting the clock back.
+To combat this,
+.Nm
+uses a monotonic clock (which never moves backwards) for its time stamps
+if the system supports it.
+.Pp
+.Nm
+will not honor time stamps set far in the future.
+Time stamps with a date greater than current_time + 2 *
+.Li TIMEOUT
+will be ignored and
+.Nm
+will log and complain.
+.Pp
+If the
+.Em timestamp_type
+option is set to
+.Dq tty ,
+the time stamp record includes the device number of the terminal
+the user authenticated with.
+This provides per-terminal granularity but time stamp records may still
+outlive the user's session.
+.Pp
+Unless the
+.Em timestamp_type
+option is set to
+.Dq global ,
+the time stamp record also includes the session ID of the process
+that last authenticated.
+This prevents processes in different terminal sessions from using
+the same time stamp record.
+On systems where a process's start time can be queried,
+the start time of the session leader
+is recorded in the time stamp record.
+If no terminal is present or the
+.Em timestamp_type
+option is set to
+.Dq ppid ,
+the start time of the parent process is used instead.
+In most cases this will prevent a time stamp record from being re-used
+without the user entering a password when logging out and back in again.
+.Sh DEBUGGING
+Versions 1.8.4 and higher of the
+.Nm
+plugin support a flexible debugging framework that can help track
+down what the plugin is doing internally if there is a problem.
+This can be configured in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+The
+.Nm
+plugin uses the same debug flag format as the
+.Nm sudo
+front-end:
+.Em subsystem Ns @ Ns Em priority .
+.Pp
+The priorities used by
+.Nm ,
+in order of decreasing severity,
+are:
+.Em crit , err , warn , notice , diag , info , trace
+and
+.Em debug .
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+.Em notice
+would include debug messages logged at
+.Em notice
+and higher.
+.Pp
+The following subsystems are used by the
+.Nm
+plugin:
+.Bl -tag -width 8n
+.It Em alias
+.Li User_Alias ,
+.Li Runas_Alias ,
+.Li Host_Alias
+and
+.Li Cmnd_Alias
+processing
+.It Em all
+matches every subsystem
+.It Em audit
+BSM and Linux audit code
+.It Em auth
+user authentication
+.It Em defaults
+.Em sudoers
+file
+.Em Defaults
+settings
+.It Em env
+environment handling
+.It Em ldap
+LDAP-based sudoers
+.It Em logging
+logging support
+.It Em match
+matching of users, groups, hosts and netgroups in the
+.Em sudoers
+file
+.It Em netif
+network interface handling
+.It Em nss
+network service switch handling in
+.Nm
+.It Em parser
+.Em sudoers
+file parsing
+.It Em perms
+permission setting
+.It Em plugin
+The equivalent of
+.Em main
+for the plugin.
+.It Em pty
+pseudo-terminal related code
+.It Em rbtree
+redblack tree internals
+.It Em sssd
+SSSD-based sudoers
+.It Em util
+utility functions
+.El
+For example:
+.Bd -literal
+Debug sudo /var/log/sudo_debug match@info,nss@info
+.Ed
+.Pp
+For more information, see the
+.Xr sudo.conf @mansectform@
+manual.
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr su 1 ,
+.Xr fnmatch 3 ,
+.Xr glob 3 ,
+.Xr mktemp 3 ,
+.Xr strftime 3 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers.ldap @mansectform@ ,
+.Xr sudoers_timestamp @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr visudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+The
+.Em sudoers
+file should
+.Sy always
+be edited by the
+.Nm visudo
+utility which locks the file and checks for syntax errors.
+If
+.Em sudoers
+contains syntax errors,
+.Nm sudo
+may refuse to run, which is a serious problem if
+.Nm sudo
+is your only method of obtaining superuser privileges.
+Recent versions of
+.Nm
+will attempt to recover after a syntax error by ignoring the rest of
+the line after encountering an error.
+Older versions of
+.Nm sudo
+will not run if
+.Em sudoers
+contains a syntax error.
+.Pp
+When using netgroups of machines (as opposed to users), if you
+store fully qualified host name in the netgroup (as is usually the
+case), you either need to have the machine's host name be fully qualified
+as returned by the
+.Li hostname
+command or use the
+.Em fqdn
+option in
+.Em sudoers .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers_timestamp.man.in b/doc/sudoers_timestamp.man.in
new file mode 100644
index 0000000..2f60f03
--- /dev/null
+++ b/doc/sudoers_timestamp.man.in
@@ -0,0 +1,312 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2017-2020 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.
+.\"
+.TH "SUDOERS_TIMESTAMP" "@mansectform@" "October 20, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers_timestamp\fR
+\- Sudoers Time Stamp Format
+.SH "DESCRIPTION"
+The
+\fBsudoers\fR
+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
+minutes unless overridden by the
+\fItimestamp_timeout\fR
+option)
+\&.
+By default,
+\fBsudoers\fR
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+\fItimestamp_type\fR
+option can be used to select the type of time stamp record
+\fBsudoers\fR
+will use.
+.PP
+A multi-record time stamp file format was introduced in
+\fBsudo\fR
+1.8.10 that uses a single file per user.
+Previously, a separate file was used for each user and terminal
+combination unless tty-based time stamps were disabled.
+The new format is extensible and records of multiple types and versions
+may coexist within the same file.
+.PP
+All records, regardless of type or version, begin with a 16-bit version
+number and a 16-bit record size.
+.PP
+Time stamp records have the following structure:
+.nf
+.sp
+.RS 0n
+/* Time stamp entry types */
+#define TS_GLOBAL 0x01 /* not restricted by tty or ppid */
+#define TS_TTY 0x02 /* restricted by tty */
+#define TS_PPID 0x03 /* restricted by ppid */
+#define TS_LOCKEXCL 0x04 /* special lock record */
+
+/* Time stamp flags */
+#define TS_DISABLED 0x01 /* entry disabled */
+#define TS_ANYUID 0x02 /* ignore uid, only valid in key */
+
+struct timestamp_entry {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec start_time; /* session/ppid start time */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+.RE
+.fi
+.PP
+The timestamp_entry struct fields are as follows:
+.TP 6n
+version
+The version number of the timestamp_entry struct.
+New entries are created with a version number of 2.
+Records with different version numbers may coexist in the
+same file but are not inter-operable.
+.TP 6n
+size
+The size of the record in bytes.
+.TP 6n
+type
+The record type, currently
+\fRTS_GLOBAL\fR,
+\fRTS_TTY\fR,
+or
+\fRTS_PPID\fR.
+.TP 6n
+flags
+.br
+Zero or more record flags which can be bit-wise ORed together.
+Supported flags are
+\fRTS_DISABLED\fR,
+for records disabled via
+\fBsudo\fR
+\fB\-k\fR
+and
+\fRTS_ANYUID\fR,
+which is used only when matching records.
+.TP 6n
+auth_uid
+The user-ID that was used for authentication.
+Depending on the value of the
+\fIrootpw\fR,
+\fIrunaspw\fR
+and
+\fItargetpw\fR
+options, the user-ID may be that of the invoking user, the root user,
+the default runas user or the target user.
+.TP 6n
+sid
+The ID of the user's terminal session, if present.
+The session ID is only used when matching records of type
+\fRTS_TTY\fR.
+.TP 6n
+start_time
+The start time of the session leader for records of type
+\fRTS_TTY\fR
+or of the parent process for records of type
+\fRTS_PPID\fR.
+The
+\fIstart_time\fR
+is used to help prevent re-use of a time stamp record after a
+user has logged out.
+Not all systems support a method to easily retrieve a process's
+start time.
+The
+\fIstart_time\fR
+field was added in
+\fBsudoers\fR
+version 1.8.22 for the second revision of the timestamp_entry struct.
+.TP 6n
+ts
+The actual time stamp.
+A monotonic time source (which does not move backward) is used if the
+system supports it.
+Where possible,
+\fBsudoers\fR
+uses a monotonic timer that increments even while the system
+is suspended.
+The value of
+\fIts\fR
+is updated each time a command is run via
+\fBsudo\fR.
+If the difference between
+\fIts\fR
+and the current time is less than the value of the
+\fItimestamp_timeout\fR
+option, no password is required.
+.TP 6n
+u.ttydev
+The device number of the terminal associated with the session for
+records of type
+\fRTS_TTY\fR.
+.TP 6n
+u.ppid
+The ID of the parent process for records of type
+\fRTS_PPID\fR.
+.SH "LOCKING"
+In
+\fBsudoers\fR
+versions 1.8.10 through 1.8.14, the entire time stamp file was
+locked for exclusive access when reading or writing to the file.
+Starting in
+\fBsudoers\fR
+1.8.15, individual records are locked in the time stamp file instead
+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
+\fRTS_LOCKEXCL\fR
+and is used as a
+\fIlock\fR
+record to prevent more than one
+\fBsudo\fR
+process from adding a new record at the same time.
+Once the desired time stamp record has been located or created (and
+locked), the
+\fRTS_LOCKEXCL\fR
+record is unlocked.
+The lock on the individual time stamp record, however, is held until
+authentication is complete.
+This allows
+\fBsudoers\fR
+to avoid prompting for a password multiple times when it
+is used more than once in a pipeline.
+.PP
+Records of type
+\fRTS_GLOBAL\fR
+cannot be locked for a long period of time since doing so would
+interfere with other
+\fBsudo\fR
+processes.
+Instead, a separate lock record is used to prevent multiple
+\fBsudo\fR
+processes using the same terminal (or parent process ID) from
+prompting for a password as the same time.
+.SH "SEE ALSO"
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "HISTORY"
+Originally,
+\fBsudo\fR
+used a single zero-length file per user and the file's modification
+time was used as the time stamp.
+Later versions of
+\fBsudo\fR
+added restrictions on the ownership of the time stamp files and
+directory as well as checks on the validity of the time stamp itself.
+Notable changes were introduced in the following
+\fBsudo\fR
+versions:
+.TP 6n
+1.4.0
+.br
+Support for tty-based time stamp file was added
+by appending the terminal name to the time stamp file name.
+.TP 6n
+1.6.2
+.br
+The time stamp file was replaced by a per-user directory which
+contained any tty-based time stamp files.
+.TP 6n
+1.6.3p2
+The target user name was added to the time stamp file name when the
+\fItargetpw\fR
+option was set.
+.TP 6n
+1.7.3
+.br
+Information about the terminal device was stored in
+tty-based time stamp files for validity checks.
+This included the terminal device numbers, inode number and, on systems
+where it was not updated when the device was written to, the inode change time.
+This helped prevent re-use of the time stamp file after logout.
+.TP 6n
+1.8.6p7
+The terminal session ID was added to tty-based time stamp files to
+prevent re-use of the time stamp by the same user in a different
+terminal session.
+It also helped prevent re-use of the time stamp file on systems where
+the terminal device's inode change time was updated by writing.
+.TP 6n
+1.8.10
+A new, multi-record time stamp file format was introduced that uses a
+single file per user.
+The terminal device's change time was not included since most
+systems now update the change time after a write is performed
+as required by POSIX.
+.TP 6n
+1.8.15
+Individual records are locked in the time stamp file instead of the
+entire file and the lock is held until authentication is complete.
+.TP 6n
+1.8.22
+The start time of the terminal session leader or parent process is
+now stored in non-global time stamp records.
+This prevents re-use of the time stamp file after logout in most cases.
+.sp
+Support was added for the kernel-based tty time stamps available in
+OpenBSD
+which do not use an on-disk time stamp file.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoers_timestamp.mdoc.in b/doc/sudoers_timestamp.mdoc.in
new file mode 100644
index 0000000..d879bfa
--- /dev/null
+++ b/doc/sudoers_timestamp.mdoc.in
@@ -0,0 +1,290 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2017-2020 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.
+.\"
+.Dd October 20, 2019
+.Dt SUDOERS_TIMESTAMP @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers_timestamp
+.Nd Sudoers Time Stamp Format
+.Sh DESCRIPTION
+The
+.Nm sudoers
+plugin uses per-user time stamp files for credential caching.
+Once a user has been authenticated, they may use
+.Nm sudo
+without a password for a short period of time
+.Po
+.Li @timeout@
+minutes unless overridden by the
+.Em timestamp_timeout
+option
+.Pc .
+By default,
+.Nm sudoers
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+.Em timestamp_type
+option can be used to select the type of time stamp record
+.Nm sudoers
+will use.
+.Pp
+A multi-record time stamp file format was introduced in
+.Nm sudo
+1.8.10 that uses a single file per user.
+Previously, a separate file was used for each user and terminal
+combination unless tty-based time stamps were disabled.
+The new format is extensible and records of multiple types and versions
+may coexist within the same file.
+.Pp
+All records, regardless of type or version, begin with a 16-bit version
+number and a 16-bit record size.
+.Pp
+Time stamp records have the following structure:
+.Bd -literal
+/* Time stamp entry types */
+#define TS_GLOBAL 0x01 /* not restricted by tty or ppid */
+#define TS_TTY 0x02 /* restricted by tty */
+#define TS_PPID 0x03 /* restricted by ppid */
+#define TS_LOCKEXCL 0x04 /* special lock record */
+
+/* Time stamp flags */
+#define TS_DISABLED 0x01 /* entry disabled */
+#define TS_ANYUID 0x02 /* ignore uid, only valid in key */
+
+struct timestamp_entry {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec start_time; /* session/ppid start time */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+.Ed
+.Pp
+The timestamp_entry struct fields are as follows:
+.Bl -tag -width 4n
+.It version
+The version number of the timestamp_entry struct.
+New entries are created with a version number of 2.
+Records with different version numbers may coexist in the
+same file but are not inter-operable.
+.It size
+The size of the record in bytes.
+.It type
+The record type, currently
+.Li TS_GLOBAL ,
+.Li TS_TTY ,
+or
+.Li TS_PPID .
+.It flags
+Zero or more record flags which can be bit-wise ORed together.
+Supported flags are
+.Li TS_DISABLED ,
+for records disabled via
+.Nm sudo
+.Fl k
+and
+.Li TS_ANYUID ,
+which is used only when matching records.
+.It auth_uid
+The user-ID that was used for authentication.
+Depending on the value of the
+.Em rootpw ,
+.Em runaspw
+and
+.Em targetpw
+options, the user-ID may be that of the invoking user, the root user,
+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 .
+.It start_time
+The start time of the session leader for records of type
+.Li TS_TTY
+or of the parent process for records of type
+.Li TS_PPID .
+The
+.Em start_time
+is used to help prevent re-use of a time stamp record after a
+user has logged out.
+Not all systems support a method to easily retrieve a process's
+start time.
+The
+.Em start_time
+field was added in
+.Nm sudoers
+version 1.8.22 for the second revision of the timestamp_entry struct.
+.It ts
+The actual time stamp.
+A monotonic time source (which does not move backward) is used if the
+system supports it.
+Where possible,
+.Nm sudoers
+uses a monotonic timer that increments even while the system
+is suspended.
+The value of
+.Em ts
+is updated each time a command is run via
+.Nm sudo .
+If the difference between
+.Em ts
+and the current time is less than the value of the
+.Em timestamp_timeout
+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 .
+.It u.ppid
+The ID of the parent process for records of type
+.Li TS_PPID .
+.El
+.Sh LOCKING
+In
+.Nm sudoers
+versions 1.8.10 through 1.8.14, the entire time stamp file was
+locked for exclusive access when reading or writing to the file.
+Starting in
+.Nm sudoers
+1.8.15, individual records are locked in the time stamp file instead
+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
+and is used as a
+.Em lock
+record to prevent more than one
+.Nm sudo
+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
+record is unlocked.
+The lock on the individual time stamp record, however, is held until
+authentication is complete.
+This allows
+.Nm sudoers
+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
+cannot be locked for a long period of time since doing so would
+interfere with other
+.Nm sudo
+processes.
+Instead, a separate lock record is used to prevent multiple
+.Nm sudo
+processes using the same terminal (or parent process ID) from
+prompting for a password as the same time.
+.Sh SEE ALSO
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh HISTORY
+Originally,
+.Nm sudo
+used a single zero-length file per user and the file's modification
+time was used as the time stamp.
+Later versions of
+.Nm sudo
+added restrictions on the ownership of the time stamp files and
+directory as well as checks on the validity of the time stamp itself.
+Notable changes were introduced in the following
+.Nm sudo
+versions:
+.Bl -tag -width 4n
+.It 1.4.0
+Support for tty-based time stamp file was added
+by appending the terminal name to the time stamp file name.
+.It 1.6.2
+The time stamp file was replaced by a per-user directory which
+contained any tty-based time stamp files.
+.It 1.6.3p2
+The target user name was added to the time stamp file name when the
+.Em targetpw
+option was set.
+.It 1.7.3
+Information about the terminal device was stored in
+tty-based time stamp files for validity checks.
+This included the terminal device numbers, inode number and, on systems
+where it was not updated when the device was written to, the inode change time.
+This helped prevent re-use of the time stamp file after logout.
+.It 1.8.6p7
+The terminal session ID was added to tty-based time stamp files to
+prevent re-use of the time stamp by the same user in a different
+terminal session.
+It also helped prevent re-use of the time stamp file on systems where
+the terminal device's inode change time was updated by writing.
+.It 1.8.10
+A new, multi-record time stamp file format was introduced that uses a
+single file per user.
+The terminal device's change time was not included since most
+systems now update the change time after a write is performed
+as required by POSIX.
+.It 1.8.15
+Individual records are locked in the time stamp file instead of the
+entire file and the lock is held until authentication is complete.
+.It 1.8.22
+The start time of the terminal session leader or parent process is
+now stored in non-global time stamp records.
+This prevents re-use of the time stamp file after logout in most cases.
+.Pp
+Support was added for the kernel-based tty time stamps available in
+.Ox
+which do not use an on-disk time stamp file.
+.El
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm sudo ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoreplay.man.in b/doc/sudoreplay.man.in
new file mode 100644
index 0000000..4401516
--- /dev/null
+++ b/doc/sudoreplay.man.in
@@ -0,0 +1,519 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2020 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.
+.\"
+.TH "SUDOREPLAY" "@mansectsu@" "May 18, 2020" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoreplay\fR
+\- replay sudo session logs
+.SH "SYNOPSIS"
+.HP 11n
+\fBsudoreplay\fR
+[\fB\-FhnRS\fR]
+[\fB\-d\fR\ \fIdir\fR]
+[\fB\-f\fR\ \fIfilter\fR]
+[\fB\-m\fR\ \fInum\fR]
+[\fB\-s\fR\ \fInum\fR]
+ID
+.HP 11n
+\fBsudoreplay\fR
+[\fB\-h\fR]
+[\fB\-d\fR\ \fIdir\fR]
+\fB\-l\fR
+[search\ expression]
+.SH "DESCRIPTION"
+\fBsudoreplay\fR
+plays back or lists the output logs created by
+\fBsudo\fR.
+When replaying,
+\fBsudoreplay\fR
+can play the session back in real-time, or the playback speed may be
+adjusted (faster or slower) based on the command line options.
+.PP
+The
+\fIID\fR
+should either be a six character sequence of digits and
+upper case letters, e.g.,
+\fR0100A5\fR,
+a pattern matching the
+\fIiolog_file\fR
+option in the
+\fIsudoers\fR
+file, or a path name.
+Path names may be relative to the
+\fIiolog_dir\fR
+option in the
+\fIsudoers\fR
+file (unless overridden by the
+\fB\-d\fR
+option) or fully qualified, beginning with a
+\(oq/\(cq
+character.
+When a command is run via
+\fBsudo\fR
+with
+\fIlog_output\fR
+enabled in the
+\fIsudoers\fR
+file, a
+\fRTSID=ID\fR
+string is logged via syslog or to the
+\fBsudo\fR
+log file.
+The
+\fIID\fR
+may also be determined using
+\fBsudoreplay\fR's
+list mode.
+.PP
+In list mode,
+\fBsudoreplay\fR
+can be used to find the ID of a session based on a number of criteria
+such as the user, tty or command run.
+.PP
+In replay mode, if the standard input and output are connected to a terminal
+and the
+\fB\-n\fR
+option is not specified,
+\fBsudoreplay\fR
+will operate interactively.
+In interactive mode,
+\fBsudoreplay\fR
+will attempt to adjust the terminal size to match that of the session and
+write directly to the terminal (not all terminals support this).
+Additionally, it will poll the keyboard and act on the following keys:
+.TP 14n
+\(oq\fR\en\fR\(cq or \(oq\fR\er\fR\(cq
+Skip to the next replay event; useful for long pauses.
+.TP 14n
+\(oq\fR\ \fR\(cq (space)
+Pause output; press any key to resume.
+.TP 14n
+\(oq<\(cq
+Reduce the playback speed by one half.
+.TP 14n
+\(oq>\(cq
+Double the playback speed.
+.PP
+The session can be interrupted via control-C.
+When the session has finished, the terminal is restored to its
+original size if it was changed during playback.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-d\fR \fIdir\fR, \fB\--directory\fR=\fIdir\fR
+Store session logs in
+\fIdir\fR
+instead of the default,
+\fI@iolog_dir@\fR.
+.TP 12n
+\fB\-f\fR \fIfilter\fR, \fB\--filter\fR=\fIfilter\fR
+Select which I/O type(s) to display.
+By default,
+\fBsudoreplay\fR
+will display the command's standard output, standard error and tty output.
+The
+\fIfilter\fR
+argument is a comma-separated list, consisting of one or more of following:
+\fIstdin\fR,
+\fIstdout\fR,
+\fIstderr\fR,
+\fIttyin\fR,
+and
+\fIttyout\fR.
+.TP 12n
+\fB\-F\fR, \fB\--follow\fR
+Enable
+\(lqfollow mode\(rq.
+When replaying a session,
+\fBsudoreplay\fR
+will ignore end-of-file and keep replaying until the log is complete.
+This can be used to replay a session that is still in progress,
+similar to
+\(lqtail -f\(rq.
+An I/O log file is considered to be complete when the write bits
+have been cleared on the session's timing file.
+Note that versions of
+\fBsudo\fR
+prior to 1.9.1 do not clear the write bits upon completion.
+.TP 12n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-l\fR, \fB\--list\fR [\fIsearch expression\fR]
+Enable
+\(lqlist mode\(rq.
+In this mode,
+\fBsudoreplay\fR
+will list available sessions in a format similar to the
+\fBsudo\fR
+log file format, sorted by file name (or sequence number).
+If a
+\fIsearch expression\fR
+is specified, it will be used to restrict the IDs that are displayed.
+An expression is composed of the following predicates:
+.PP
+.RS 12n
+.PD 0
+.TP 8n
+command \fIpattern\fR
+Evaluates to true if the command run matches the POSIX extended
+regular expression
+\fIpattern\fR.
+.PD
+.TP 8n
+cwd \fIdirectory\fR
+Evaluates to true if the command was run with the specified current
+working directory.
+.TP 8n
+fromdate \fIdate\fR
+Evaluates to true if the command was run on or after
+\fIdate\fR.
+See
+\fIDate and time format\fR
+for a description of supported date and time formats.
+.TP 8n
+group \fIrunas_group\fR
+Evaluates to true if the command was run with the specified
+\fIrunas_group\fR.
+Note that unless a
+\fIrunas_group\fR
+was explicitly specified when
+\fBsudo\fR
+was run this field will be empty in the log.
+.TP 8n
+host \fIhostname\fR
+Evaluates to true if the command was run on the specified
+\fIhostname\fR.
+.TP 8n
+runas \fIrunas_user\fR
+Evaluates to true if the command was run as the specified
+\fIrunas_user\fR.
+Note that
+\fBsudo\fR
+runs commands as user
+\fIroot\fR
+by default.
+.TP 8n
+todate \fIdate\fR
+Evaluates to true if the command was run on or prior to
+\fIdate\fR.
+See
+\fIDate and time format\fR
+for a description of supported date and time formats.
+.TP 8n
+tty \fItty name\fR
+Evaluates to true if the command was run on the specified terminal device.
+The
+\fItty name\fR
+should be specified without the
+\fI/dev/\fR
+prefix, e.g.,
+\fItty01\fR
+instead of
+\fI/dev/tty01\fR.
+.TP 8n
+user \fIuser name\fR
+Evaluates to true if the ID matches a command run by
+\fIuser name\fR.
+.PP
+Predicates may be abbreviated to the shortest unique string.
+.sp
+Predicates may be combined using
+\fIand\fR,
+\fIor\fR
+and
+\fI\&!\fR
+operators as well as
+\(oq\&(\(cq
+and
+\(oq\&)\(cq
+grouping (note that parentheses must generally be escaped from the shell).
+The
+\fIand\fR
+operator is optional, adjacent predicates have an implied
+\fIand\fR
+unless separated by an
+\fIor\fR.
+.RE
+.TP 12n
+\fB\-m\fR, \fB\--max-wait\fR \fImax_wait\fR
+Specify an upper bound on how long to wait between key presses or output data.
+By default,
+\fBsudoreplay\fR
+will accurately reproduce the delays between key presses or program output.
+However, this can be tedious when the session includes long pauses.
+When the
+\fB\-m\fR
+option is specified,
+\fBsudoreplay\fR
+will limit these pauses to at most
+\fImax_wait\fR
+seconds.
+The value may be specified as a floating point number, e.g.,
+\fI2.5\fR.
+A
+\fImax_wait\fR
+of zero or less will eliminate the pauses entirely.
+.TP 12n
+\fB\-n\fR, \fB\--non-interactive\fR
+Do not prompt for user input or attempt to re-size the terminal.
+The session is written to the standard output, not directly to
+the user's terminal.
+.TP 12n
+\fB\-R\fR, \fB\--no-resize\fR
+Do not attempt to re-size the terminal to match the terminal size
+of the session.
+.TP 12n
+\fB\-S\fR, \fB\--suspend-wait\fR
+Wait while the command was suspended.
+By default,
+\fBsudoreplay\fR
+will ignore the time interval between when the command was suspended
+and when it was resumed.
+If the
+\fB\-S\fR
+option is specified,
+\fBsudoreplay\fR
+will wait instead.
+.TP 12n
+\fB\-s\fR, \fB\--speed\fR \fIspeed_factor\fR
+This option causes
+\fBsudoreplay\fR
+to adjust the number of seconds it will wait between key presses or
+program output.
+This can be used to slow down or speed up the display.
+For example, a
+\fIspeed_factor\fR
+of
+\fI2\fR
+would make the output twice as fast whereas a
+\fIspeed_factor\fR
+of
+\fI.5\fR
+would make the output twice as slow.
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudoreplay\fR
+versions version number and exit.
+.SS "Date and time format"
+The time and date may be specified multiple ways, common formats include:
+.TP 8n
+HH:MM:SS am MM/DD/CCYY timezone
+24 hour time may be used in place of am/pm.
+.TP 8n
+HH:MM:SS am Month, Day Year timezone
+24 hour time may be used in place of am/pm, and month and day names
+may be abbreviated.
+Note that month and day of the week names must be specified in English.
+.TP 8n
+CCYY-MM-DD HH:MM:SS
+ISO time format
+.TP 8n
+DD Month CCYY HH:MM:SS
+The month name may be abbreviated.
+.PP
+Either time or date may be omitted, the am/pm and timezone are optional.
+If no date is specified, the current day is assumed; if no time is
+specified, the first second of the specified date is used.
+The less significant parts of both time and date may also be omitted,
+in which case zero is assumed.
+.PP
+The following are all valid time and date specifications:
+.TP 8n
+now
+The current time and date.
+.TP 8n
+tomorrow
+Exactly one day from now.
+.TP 8n
+yesterday
+24 hours ago.
+.TP 8n
+2 hours ago
+2 hours ago.
+.TP 8n
+next Friday
+The first second of the Friday in the next (upcoming) week.
+Not to be confused with
+\(lqthis Friday\(rq
+which would match the Friday of the current week.
+.TP 8n
+last week
+The current time but 7 days ago.
+This is equivalent to
+\(lqa week ago\(rq.
+.TP 8n
+a fortnight ago
+The current time but 14 days ago.
+.TP 8n
+10:01 am 9/17/2009
+10:01 am, September 17, 2009.
+.TP 8n
+10:01 am
+10:01 am on the current day.
+.TP 8n
+10
+10:00 am on the current day.
+.TP 8n
+9/17/2009
+00:00 am, September 17, 2009.
+.TP 8n
+10:01 am Sep 17, 2009
+10:01 am, September 17, 2009.
+.PP
+Note that relative time specifications do not always work as expected.
+For example, the
+\(lqnext\(rq
+qualifier is intended to be used in conjunction with a day such as
+\(lqnext Monday\(rq.
+When used with units of weeks, months, years, etc
+the result will be one more than expected.
+For example,
+\(lqnext week\(rq
+will result in a time exactly two weeks from now, which is probably
+not what was intended.
+This will be addressed in a future version of
+\fBsudoreplay\fR.
+.SS "Debugging sudoreplay"
+\fBsudoreplay\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+\fRDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+please refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Debugging framework configuration
+.TP 26n
+\fI@iolog_dir@\fR
+The default I/O log directory.
+.TP 26n
+\fI@iolog_dir@/00/00/01/log\fR
+Example session log info.
+.TP 26n
+\fI@iolog_dir@/00/00/01/log.json\fR
+Example session log info (JSON format).
+.TP 26n
+\fI@iolog_dir@/00/00/01/stdin\fR
+Example session standard input log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/stdout\fR
+Example session standard output log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/stderr\fR
+Example session standard error log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/ttyin\fR
+Example session tty input file.
+.TP 26n
+\fI@iolog_dir@/00/00/01/ttyout\fR
+Example session tty output file.
+.TP 26n
+\fI@iolog_dir@/00/00/01/timing\fR
+Example session timing file.
+.PP
+Note that the
+\fIstdin\fR,
+\fIstdout\fR
+and
+\fIstderr\fR
+files will be empty unless
+\fBsudo\fR
+was used as part of a pipeline for a particular command.
+.SH "EXAMPLES"
+List sessions run by user
+\fImillert\fR:
+.nf
+.sp
+.RS 6n
+# sudoreplay -l user millert
+.RE
+.fi
+.PP
+List sessions run by user
+\fIbob\fR
+with a command containing the string vi:
+.nf
+.sp
+.RS 6n
+# sudoreplay -l user bob command vi
+.RE
+.fi
+.PP
+List sessions run by user
+\fIjeff\fR
+that match a regular expression:
+.nf
+.sp
+.RS 6n
+# sudoreplay -l user jeff command '/bin/[a-z]*sh'
+.RE
+.fi
+.PP
+List sessions run by jeff or bob on the console:
+.nf
+.sp
+.RS 6n
+# sudoreplay -l ( user jeff or user bob ) tty console
+.RE
+.fi
+.SH "SEE ALSO"
+script(1),
+sudo.conf(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBsudoreplay\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudoreplay\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/sudoreplay.mdoc.in b/doc/sudoreplay.mdoc.in
new file mode 100644
index 0000000..f7adfa8
--- /dev/null
+++ b/doc/sudoreplay.mdoc.in
@@ -0,0 +1,461 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2020 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.
+.\"
+.Dd May 18, 2020
+.Dt SUDOREPLAY @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoreplay
+.Nd replay sudo session logs
+.Sh SYNOPSIS
+.Nm sudoreplay
+.Op Fl FhnRS
+.Op Fl d Ar dir
+.Op Fl f Ar filter
+.Op Fl m Ar num
+.Op Fl s Ar num
+ID
+.Pp
+.Nm
+.Op Fl h
+.Op Fl d Ar dir
+.Fl l
+.Op search expression
+.Sh DESCRIPTION
+.Nm
+plays back or lists the output logs created by
+.Nm sudo .
+When replaying,
+.Nm
+can play the session back in real-time, or the playback speed may be
+adjusted (faster or slower) based on the command line options.
+.Pp
+The
+.Em ID
+should either be a six character sequence of digits and
+upper case letters, e.g.,
+.Li 0100A5 ,
+a pattern matching the
+.Em iolog_file
+option in the
+.Em sudoers
+file, or a path name.
+Path names may be relative to the
+.Em iolog_dir
+option in the
+.Em sudoers
+file (unless overridden by the
+.Fl d
+option) or fully qualified, beginning with a
+.Ql /
+character.
+When a command is run via
+.Nm sudo
+with
+.Em log_output
+enabled in the
+.Em sudoers
+file, a
+.Li TSID=ID
+string is logged via syslog or to the
+.Nm sudo
+log file.
+The
+.Em ID
+may also be determined using
+.Nm sudoreplay Ns 's
+list mode.
+.Pp
+In list mode,
+.Nm
+can be used to find the ID of a session based on a number of criteria
+such as the user, tty or command run.
+.Pp
+In replay mode, if the standard input and output are connected to a terminal
+and the
+.Fl n
+option is not specified,
+.Nm
+will operate interactively.
+In interactive mode,
+.Nm
+will attempt to adjust the terminal size to match that of the session and
+write directly to the terminal (not all terminals support this).
+Additionally, it will poll the keyboard and act on the following keys:
+.Bl -tag -width 12n
+.It So Li \en Sc No or So Li \er Sc
+Skip to the next replay event; useful for long pauses.
+.It So Li \ Sc Pq space
+Pause output; press any key to resume.
+.It Ql <
+Reduce the playback speed by one half.
+.It Ql >
+Double the playback speed.
+.El
+.Pp
+The session can be interrupted via control-C.
+When the session has finished, the terminal is restored to its
+original size if it was changed during playback.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d Ar dir , Fl -directory Ns = Ns Ar dir
+Store session logs in
+.Ar dir
+instead of the default,
+.Pa @iolog_dir@ .
+.It Fl f Ar filter , Fl -filter Ns = Ns Ar filter
+Select which I/O type(s) to display.
+By default,
+.Nm
+will display the command's standard output, standard error and tty output.
+The
+.Ar filter
+argument is a comma-separated list, consisting of one or more of following:
+.Em stdin ,
+.Em stdout ,
+.Em stderr ,
+.Em ttyin ,
+and
+.Em ttyout .
+.It Fl F , -follow
+Enable
+.Dq follow mode .
+When replaying a session,
+.Nm
+will ignore end-of-file and keep replaying until the log is complete.
+This can be used to replay a session that is still in progress,
+similar to
+.Dq tail -f .
+An I/O log file is considered to be complete when the write bits
+have been cleared on the session's timing file.
+Note that versions of
+.Nm sudo
+prior to 1.9.1 do not clear the write bits upon completion.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl l , -list Op Ar search expression
+Enable
+.Dq list mode .
+In this mode,
+.Nm
+will list available sessions in a format similar to the
+.Nm sudo
+log file format, sorted by file name (or sequence number).
+If a
+.Ar search expression
+is specified, it will be used to restrict the IDs that are displayed.
+An expression is composed of the following predicates:
+.Bl -tag -width 6n
+.It command Ar pattern
+Evaluates to true if the command run matches the POSIX extended
+regular expression
+.Ar pattern .
+.It cwd Ar directory
+Evaluates to true if the command was run with the specified current
+working directory.
+.It fromdate Ar date
+Evaluates to true if the command was run on or after
+.Ar date .
+See
+.Sx Date and time format
+for a description of supported date and time formats.
+.It group Ar runas_group
+Evaluates to true if the command was run with the specified
+.Ar runas_group .
+Note that unless a
+.Ar runas_group
+was explicitly specified when
+.Nm sudo
+was run this field will be empty in the log.
+.It host Ar hostname
+Evaluates to true if the command was run on the specified
+.Ar hostname .
+.It runas Ar runas_user
+Evaluates to true if the command was run as the specified
+.Ar runas_user .
+Note that
+.Nm sudo
+runs commands as user
+.Em root
+by default.
+.It todate Ar date
+Evaluates to true if the command was run on or prior to
+.Ar date .
+See
+.Sx Date and time format
+for a description of supported date and time formats.
+.It tty Ar tty name
+Evaluates to true if the command was run on the specified terminal device.
+The
+.Ar tty name
+should be specified without the
+.Pa /dev/
+prefix, e.g.,
+.Pa tty01
+instead of
+.Pa /dev/tty01 .
+.It user Ar user name
+Evaluates to true if the ID matches a command run by
+.Ar user name .
+.El
+.Pp
+Predicates may be abbreviated to the shortest unique string.
+.Pp
+Predicates may be combined using
+.Em and ,
+.Em or
+and
+.Em \&!
+operators as well as
+.Ql \&(
+and
+.Ql \&)
+grouping (note that parentheses must generally be escaped from the shell).
+The
+.Em and
+operator is optional, adjacent predicates have an implied
+.Em and
+unless separated by an
+.Em or .
+.It Fl m , -max-wait Ar max_wait
+Specify an upper bound on how long to wait between key presses or output data.
+By default,
+.Nm
+will accurately reproduce the delays between key presses or program output.
+However, this can be tedious when the session includes long pauses.
+When the
+.Fl m
+option is specified,
+.Nm
+will limit these pauses to at most
+.Em max_wait
+seconds.
+The value may be specified as a floating point number, e.g.,
+.Em 2.5 .
+A
+.Em max_wait
+of zero or less will eliminate the pauses entirely.
+.It Fl n , -non-interactive
+Do not prompt for user input or attempt to re-size the terminal.
+The session is written to the standard output, not directly to
+the user's terminal.
+.It Fl R , -no-resize
+Do not attempt to re-size the terminal to match the terminal size
+of the session.
+.It Fl S , -suspend-wait
+Wait while the command was suspended.
+By default,
+.Nm
+will ignore the time interval between when the command was suspended
+and when it was resumed.
+If the
+.Fl S
+option is specified,
+.Nm
+will wait instead.
+.It Fl s , -speed Ar speed_factor
+This option causes
+.Nm
+to adjust the number of seconds it will wait between key presses or
+program output.
+This can be used to slow down or speed up the display.
+For example, a
+.Ar speed_factor
+of
+.Em 2
+would make the output twice as fast whereas a
+.Ar speed_factor
+of
+.Em .5
+would make the output twice as slow.
+.It Fl V , -version
+Print the
+.Nm
+versions version number and exit.
+.El
+.Ss Date and time format
+The time and date may be specified multiple ways, common formats include:
+.Bl -tag -width 6n
+.It HH:MM:SS am MM/DD/CCYY timezone
+24 hour time may be used in place of am/pm.
+.It HH:MM:SS am Month, Day Year timezone
+24 hour time may be used in place of am/pm, and month and day names
+may be abbreviated.
+Note that month and day of the week names must be specified in English.
+.It CCYY-MM-DD HH:MM:SS
+ISO time format
+.It DD Month CCYY HH:MM:SS
+The month name may be abbreviated.
+.El
+.Pp
+Either time or date may be omitted, the am/pm and timezone are optional.
+If no date is specified, the current day is assumed; if no time is
+specified, the first second of the specified date is used.
+The less significant parts of both time and date may also be omitted,
+in which case zero is assumed.
+.Pp
+The following are all valid time and date specifications:
+.Bl -tag -width 6n
+.It now
+The current time and date.
+.It tomorrow
+Exactly one day from now.
+.It yesterday
+24 hours ago.
+.It 2 hours ago
+2 hours ago.
+.It next Friday
+The first second of the Friday in the next (upcoming) week.
+Not to be confused with
+.Dq this Friday
+which would match the Friday of the current week.
+.It last week
+The current time but 7 days ago.
+This is equivalent to
+.Dq a week ago .
+.It a fortnight ago
+The current time but 14 days ago.
+.It 10:01 am 9/17/2009
+10:01 am, September 17, 2009.
+.It 10:01 am
+10:01 am on the current day.
+.It 10
+10:00 am on the current day.
+.It 9/17/2009
+00:00 am, September 17, 2009.
+.It 10:01 am Sep 17, 2009
+10:01 am, September 17, 2009.
+.El
+.Pp
+Note that relative time specifications do not always work as expected.
+For example, the
+.Dq next
+qualifier is intended to be used in conjunction with a day such as
+.Dq next Monday .
+When used with units of weeks, months, years, etc
+the result will be one more than expected.
+For example,
+.Dq next week
+will result in a time exactly two weeks from now, which is probably
+not what was intended.
+This will be addressed in a future version of
+.Nm .
+.Ss Debugging sudoreplay
+.Nm
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+.Li Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+please refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Debugging framework configuration
+.It Pa @iolog_dir@
+The default I/O log directory.
+.It Pa @iolog_dir@/00/00/01/log
+Example session log info.
+.It Pa @iolog_dir@/00/00/01/log.json
+Example session log info (JSON format).
+.It Pa @iolog_dir@/00/00/01/stdin
+Example session standard input log.
+.It Pa @iolog_dir@/00/00/01/stdout
+Example session standard output log.
+.It Pa @iolog_dir@/00/00/01/stderr
+Example session standard error log.
+.It Pa @iolog_dir@/00/00/01/ttyin
+Example session tty input file.
+.It Pa @iolog_dir@/00/00/01/ttyout
+Example session tty output file.
+.It Pa @iolog_dir@/00/00/01/timing
+Example session timing file.
+.El
+.Pp
+Note that the
+.Em stdin ,
+.Em stdout
+and
+.Em stderr
+files will be empty unless
+.Nm sudo
+was used as part of a pipeline for a particular command.
+.Sh EXAMPLES
+List sessions run by user
+.Em millert :
+.Bd -literal -offset indent
+# sudoreplay -l user millert
+.Ed
+.Pp
+List sessions run by user
+.Em bob
+with a command containing the string vi:
+.Bd -literal -offset indent
+# sudoreplay -l user bob command vi
+.Ed
+.Pp
+List sessions run by user
+.Em jeff
+that match a regular expression:
+.Bd -literal -offset indent
+# sudoreplay -l user jeff command '/bin/[a-z]*sh'
+.Ed
+.Pp
+List sessions run by jeff or bob on the console:
+.Bd -literal -offset indent
+# sudoreplay -l ( user jeff or user bob ) tty console
+.Ed
+.Sh SEE ALSO
+.Xr script 1 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/visudo.man.in b/doc/visudo.man.in
new file mode 100644
index 0000000..d068e83
--- /dev/null
+++ b/doc/visudo.man.in
@@ -0,0 +1,475 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1996,1998-2005, 2007-2020
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.TH "VISUDO" "@mansectsu@" "August 27, 2020" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBvisudo\fR
+\- edit the sudoers file
+.SH "SYNOPSIS"
+.HP 7n
+\fBvisudo\fR
+[\fB\-chqsV\fR]
+[[\fB\-f\fR]\ \fIsudoers\fR]
+.SH "DESCRIPTION"
+\fBvisudo\fR
+edits the
+\fIsudoers\fR
+file in a safe fashion, analogous to
+vipw(@mansectsu@).
+\fBvisudo\fR
+locks the
+\fIsudoers\fR
+file against multiple simultaneous edits, performs basic validity checks,
+and checks for syntax errors before installing the edited file.
+If the
+\fIsudoers\fR
+file is currently being edited you will receive a message to try again later.
+.PP
+\fBvisudo\fR
+parses the
+\fIsudoers\fR
+file after editing and will not save the changes if there is a syntax error.
+Upon finding an error,
+\fBvisudo\fR
+will print a message stating the line number(s)
+where the error occurred and the user will receive the
+\(lqWhat now?\(rq
+prompt.
+At this point the user may enter
+\(oqe\(cq
+to re-edit the
+\fIsudoers\fR
+file,
+\(oqx\(cq
+to exit without saving the changes, or
+\(oqQ\(cq
+to quit and save changes.
+The
+\(oqQ\(cq
+option should be used with extreme caution because if
+\fBvisudo\fR
+believes there to be a syntax error, so will
+\fBsudo\fR
+and no one will be able to run
+\fBsudo\fR
+again until the error is fixed.
+If
+\(oqe\(cq
+is typed to edit the
+\fIsudoers\fR
+file after a syntax error has been detected, the cursor will be placed on
+the line where the error occurred (if the editor supports this feature).
+.PP
+There are two
+\fIsudoers\fR
+settings that determine which editor
+\fBvisudo\fR
+will run.
+.TP 10n
+editor
+A colon
+(\(oq:\&\(cq)
+separated list of editors allowed to be used with
+\fBvisudo\fR.
+\fBvisudo\fR
+will choose the editor that matches the user's
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variable if possible, or the first editor in the
+list that exists and is executable.
+Note that
+\fBsudo\fR
+does not preserve the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables unless they are present in the
+\fIenv_keep\fR
+list or the
+\fIenv_reset\fR
+option is disabled in the
+\fIsudoers\fR
+file.
+The default editor path is
+\fI@editor@\fR
+which can be set at compile time via the
+\fR--with-editor\fR
+configure option.
+.TP 10n
+env_editor
+If set,
+\fBvisudo\fR
+will use the value of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables before falling back on the default editor list.
+Note that
+\fBvisudo\fR
+is typically run as root so this option may allow a user with
+\fBvisudo\fR
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+\(lqsafe\(rq
+editors int the
+\fIeditor\fR
+variable.
+\fBvisudo\fR
+will then only use
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+if they match a value specified in
+\fIeditor\fR.
+If the
+\fIenv_reset\fR
+flag is enabled, the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+and/or
+\fREDITOR\fR
+environment variables must be present in the
+\fIenv_keep\fR
+list for the
+\fIenv_editor\fR
+flag to function when
+\fBvisudo\fR
+is invoked via
+\fBsudo\fR.
+The default value is
+\fI@env_editor@\fR,
+which can be set at compile time via the
+\fR--with-env-editor\fR
+configure option.
+.PP
+The options are as follows:
+.TP 12n
+\fB\-c\fR, \fB\--check\fR
+Enable
+\fIcheck-only\fR
+mode.
+The existing
+\fIsudoers\fR
+file (and any other files it includes) will be
+checked for syntax errors.
+If the path to the
+\fIsudoers\fR
+file was not specified,
+\fBvisudo\fR
+will also check the file owner and mode.
+A message will be printed to the standard output describing the status of
+\fIsudoers\fR
+unless the
+\fB\-q\fR
+option was specified.
+If the check completes successfully,
+\fBvisudo\fR
+will exit with a value of 0.
+If an error is encountered,
+\fBvisudo\fR
+will exit with a value of 1.
+.TP 12n
+\fB\-f\fR \fIsudoers\fR, \fB\--file\fR=\fIsudoers\fR
+Specify an alternate
+\fIsudoers\fR
+file location, see below.
+As of version 1.8.27, the
+\fIsudoers\fR
+path can be specified without using the
+\fB\-f\fR
+option.
+.TP 12n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 12n
+\fB\-q\fR, \fB\--quiet\fR
+Enable
+\fIquiet\fR
+mode.
+In this mode details about syntax errors are not printed.
+This option is only useful when combined with
+the
+\fB\-c\fR
+option.
+.TP 12n
+\fB\-s\fR, \fB\--strict\fR
+Enable
+\fIstrict\fR
+checking of the
+\fIsudoers\fR
+file.
+If an alias is referenced but not actually defined
+or if there is a cycle in an alias,
+\fBvisudo\fR
+will consider this a syntax error.
+Note that it is not possible to differentiate between an
+alias and a host name or user name that consists solely of uppercase
+letters, digits, and the underscore
+(\(oq_\(cq)
+character.
+.TP 12n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBvisudo\fR
+and
+\fIsudoers\fR
+grammar versions and exit.
+.PP
+A
+\fIsudoers\fR
+file may be specified instead of the default,
+\fI@sysconfdir@/sudoers\fR.
+The temporary file used is the specified
+\fIsudoers\fR
+file with
+\(lq\.tmp\(rq
+appended to it.
+In
+\fIcheck-only\fR
+mode only,
+\(oq-\(cq
+may be used to indicate that
+\fIsudoers\fR
+will be read from the standard input.
+Because the policy is evaluated in its entirety, it is not sufficient
+to check an individual
+\fIsudoers\fR
+include file for syntax errors.
+.SS "Debugging and sudoers plugin arguments"
+\fBvisudo\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+\fRDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+Starting with
+\fBsudo\fR
+1.8.12,
+\fBvisudo\fR
+will also parse the arguments to the
+\fIsudoers\fR
+plugin to override the default
+\fIsudoers\fR
+path name, UID, GID and file mode.
+These arguments, if present, should be listed after the path to the plugin
+(i.e., after
+\fIsudoers.so\fR).
+Multiple arguments may be specified, separated by white space.
+For example:
+.nf
+.sp
+.RS 6n
+Plugin sudoers_policy sudoers.so sudoers_mode=0400
+.RE
+.fi
+.PP
+The following arguments are supported:
+.TP 10n
+sudoers_file=pathname
+The
+\fIsudoers_file\fR
+argument can be used to override the default path to the
+\fIsudoers\fR
+file.
+.TP 10n
+sudoers_uid=uid
+The
+\fIsudoers_uid\fR
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.TP 10n
+sudoers_gid=gid
+The
+\fIsudoers_gid\fR
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.TP 10n
+sudoers_mode=mode
+The
+\fIsudoers_mode\fR
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+please refer to its manual.
+.SH "ENVIRONMENT"
+The following environment variables may be consulted depending on
+the value of the
+\fIeditor\fR
+and
+\fIenv_editor\fR
+\fIsudoers\fR
+settings:
+.TP 17n
+\fRSUDO_EDITOR\fR
+Invoked by
+\fBvisudo\fR
+as the editor to use
+.TP 17n
+\fRVISUAL\fR
+Used by
+\fBvisudo\fR
+if
+\fRSUDO_EDITOR\fR
+is not set
+.TP 17n
+\fREDITOR\fR
+Used by
+\fBvisudo\fR
+if neither
+\fRSUDO_EDITOR\fR
+nor
+\fRVISUAL\fR
+is set
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front end configuration
+.TP 26n
+\fI@sysconfdir@/sudoers\fR
+List of who can run what
+.TP 26n
+\fI@sysconfdir@/sudoers.tmp\fR
+Default temporary file used by visudo
+.SH "DIAGNOSTICS"
+In addition to reporting
+\fIsudoers\fR
+syntax errors,
+\fBvisudo\fR
+may produce the following messages:
+.TP 6n
+\fRsudoers file busy, try again later.\fR
+Someone else is currently editing the
+\fIsudoers\fR
+file.
+.TP 6n
+\fR@sysconfdir@/sudoers: Permission denied\fR
+You didn't run
+\fBvisudo\fR
+as root.
+.TP 6n
+\fRyou do not exist in the passwd database\fR
+Your user-ID does not appear in the system passwd database.
+.TP 6n
+\fRWarning: {User,Runas,Host,Cmnd}_Alias referenced but not defined\fR
+Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
+or you have a user or host name listed that consists solely of
+uppercase letters, digits, and the underscore
+(\(oq_\(cq)
+character.
+In the latter case, you can ignore the warnings
+(\fBsudo\fR
+will not complain)
+\&.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the undefined alias was used.
+In
+\fB\-s\fR
+(strict) mode these are errors, not warnings.
+.TP 6n
+\fRWarning: unused {User,Runas,Host,Cmnd}_Alias\fR
+The specified {User,Runas,Host,Cmnd}_Alias was defined but never
+used.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the unused alias was defined.
+You may wish to comment out or remove the unused alias.
+.TP 6n
+\fRWarning: cycle in {User,Runas,Host,Cmnd}_Alias\fR
+The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
+itself, either directly or through an alias it includes.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the cycle was detected.
+This is only a warning unless
+\fBvisudo\fR
+is run in
+\fB\-s\fR
+(strict) mode as
+\fBsudo\fR
+will ignore cycles when parsing
+the
+\fIsudoers\fR
+file.
+.TP 6n
+\fRunknown defaults entry \&"name\&"\fR
+The
+\fIsudoers\fR
+file contains a
+\fRDefaults\fR
+setting not recognized by
+\fBvisudo\fR.
+.SH "SEE ALSO"
+vi(1),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@),
+vipw(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+There is no easy way to prevent a user from gaining a root shell if
+the editor used by
+\fBvisudo\fR
+allows shell escapes.
+.SH "BUGS"
+If you feel you have found a bug in
+\fBvisudo\fR,
+please submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBvisudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/license.html for complete details.
diff --git a/doc/visudo.mdoc.in b/doc/visudo.mdoc.in
new file mode 100644
index 0000000..278040b
--- /dev/null
+++ b/doc/visudo.mdoc.in
@@ -0,0 +1,457 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1996,1998-2005, 2007-2020
+.\" 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.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.Dd August 27, 2020
+.Dt VISUDO @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm visudo
+.Nd edit the sudoers file
+.Sh SYNOPSIS
+.Nm visudo
+.Op Fl chqsV
+.Op Bo Fl f Bc Ar sudoers
+.Sh DESCRIPTION
+.Nm
+edits the
+.Em sudoers
+file in a safe fashion, analogous to
+.Xr vipw @mansectsu@ .
+.Nm
+locks the
+.Em sudoers
+file against multiple simultaneous edits, performs basic validity checks,
+and checks for syntax errors before installing the edited file.
+If the
+.Em sudoers
+file is currently being edited you will receive a message to try again later.
+.Pp
+.Nm
+parses the
+.Em sudoers
+file after editing and will not save the changes if there is a syntax error.
+Upon finding an error,
+.Nm
+will print a message stating the line number(s)
+where the error occurred and the user will receive the
+.Dq What now?
+prompt.
+At this point the user may enter
+.Ql e
+to re-edit the
+.Em sudoers
+file,
+.Ql x
+to exit without saving the changes, or
+.Ql Q
+to quit and save changes.
+The
+.Ql Q
+option should be used with extreme caution because if
+.Nm
+believes there to be a syntax error, so will
+.Nm sudo
+and no one will be able to run
+.Nm sudo
+again until the error is fixed.
+If
+.Ql e
+is typed to edit the
+.Em sudoers
+file after a syntax error has been detected, the cursor will be placed on
+the line where the error occurred (if the editor supports this feature).
+.Pp
+There are two
+.Em sudoers
+settings that determine which editor
+.Nm visudo
+will run.
+.Bl -tag -width 8n
+.It editor
+A colon
+.Pq Ql :\&
+separated list of editors allowed to be used with
+.Nm .
+.Nm
+will choose the editor that matches the user's
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variable if possible, or the first editor in the
+list that exists and is executable.
+Note that
+.Nm sudo
+does not preserve the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables unless they are present in the
+.Em env_keep
+list or the
+.Em env_reset
+option is disabled in the
+.Em sudoers
+file.
+The default editor path is
+.Pa @editor@
+which can be set at compile time via the
+.Li --with-editor
+configure option.
+.It env_editor
+If set,
+.Nm
+will use the value of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables before falling back on the default editor list.
+Note that
+.Nm visudo
+is typically run as root so this option may allow a user with
+.Nm visudo
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+.Dq safe
+editors int the
+.Em editor
+variable.
+.Nm
+will then only use
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+if they match a value specified in
+.Em editor .
+If the
+.Em env_reset
+flag is enabled, the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+and/or
+.Ev EDITOR
+environment variables must be present in the
+.Em env_keep
+list for the
+.Em env_editor
+flag to function when
+.Nm
+is invoked via
+.Nm sudo .
+The default value is
+.Em @env_editor@ ,
+which can be set at compile time via the
+.Li --with-env-editor
+configure option.
+.El
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl c , -check
+Enable
+.Em check-only
+mode.
+The existing
+.Em sudoers
+file (and any other files it includes) will be
+checked for syntax errors.
+If the path to the
+.Em sudoers
+file was not specified,
+.Nm
+will also check the file owner and mode.
+A message will be printed to the standard output describing the status of
+.Em sudoers
+unless the
+.Fl q
+option was specified.
+If the check completes successfully,
+.Nm
+will exit with a value of 0.
+If an error is encountered,
+.Nm
+will exit with a value of 1.
+.It Fl f Ar sudoers , Fl -file Ns = Ns Ar sudoers
+Specify an alternate
+.Em sudoers
+file location, see below.
+As of version 1.8.27, the
+.Em sudoers
+path can be specified without using the
+.Fl f
+option.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl q , -quiet
+Enable
+.Em quiet
+mode.
+In this mode details about syntax errors are not printed.
+This option is only useful when combined with
+the
+.Fl c
+option.
+.It Fl s , -strict
+Enable
+.Em strict
+checking of the
+.Em sudoers
+file.
+If an alias is referenced but not actually defined
+or if there is a cycle in an alias,
+.Nm
+will consider this a syntax error.
+Note that it is not possible to differentiate between an
+alias and a host name or user name that consists solely of uppercase
+letters, digits, and the underscore
+.Pq Ql _
+character.
+.It Fl V , -version
+Print the
+.Nm
+and
+.Em sudoers
+grammar versions and exit.
+.El
+.Pp
+A
+.Em sudoers
+file may be specified instead of the default,
+.Pa @sysconfdir@/sudoers .
+The temporary file used is the specified
+.Em sudoers
+file with
+.Dq \.tmp
+appended to it.
+In
+.Em check-only
+mode only,
+.Ql -
+may be used to indicate that
+.Em sudoers
+will be read from the standard input.
+Because the policy is evaluated in its entirety, it is not sufficient
+to check an individual
+.Em sudoers
+include file for syntax errors.
+.Ss Debugging and sudoers plugin arguments
+.Nm
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+.Li Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+Starting with
+.Nm sudo
+1.8.12,
+.Nm
+will also parse the arguments to the
+.Em sudoers
+plugin to override the default
+.Em sudoers
+path name, UID, GID and file mode.
+These arguments, if present, should be listed after the path to the plugin
+(i.e., after
+.Pa sudoers.so ) .
+Multiple arguments may be specified, separated by white space.
+For example:
+.Bd -literal -offset indent
+Plugin sudoers_policy sudoers.so sudoers_mode=0400
+.Ed
+.Pp
+The following arguments are supported:
+.Bl -tag -width 8n
+.It sudoers_file=pathname
+The
+.Em sudoers_file
+argument can be used to override the default path to the
+.Em sudoers
+file.
+.It sudoers_uid=uid
+The
+.Em sudoers_uid
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.It sudoers_gid=gid
+The
+.Em sudoers_gid
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.It sudoers_mode=mode
+The
+.Em sudoers_mode
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.El
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+please refer to its manual.
+.Sh ENVIRONMENT
+The following environment variables may be consulted depending on
+the value of the
+.Em editor
+and
+.Em env_editor
+.Em sudoers
+settings:
+.Bl -tag -width 15n
+.It Ev SUDO_EDITOR
+Invoked by
+.Nm
+as the editor to use
+.It Ev VISUAL
+Used by
+.Nm
+if
+.Ev SUDO_EDITOR
+is not set
+.It Ev EDITOR
+Used by
+.Nm
+if neither
+.Ev SUDO_EDITOR
+nor
+.Ev VISUAL
+is set
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front end configuration
+.It Pa @sysconfdir@/sudoers
+List of who can run what
+.It Pa @sysconfdir@/sudoers.tmp
+Default temporary file used by visudo
+.El
+.Sh DIAGNOSTICS
+In addition to reporting
+.Em sudoers
+syntax errors,
+.Nm
+may produce the following messages:
+.Bl -tag -width 4n
+.It Li sudoers file busy, try again later.
+Someone else is currently editing the
+.Em sudoers
+file.
+.It Li @sysconfdir@/sudoers: Permission denied
+You didn't run
+.Nm
+as root.
+.It Li you do not exist in the passwd database
+Your user-ID does not appear in the system passwd database.
+.It Li Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined
+Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
+or you have a user or host name listed that consists solely of
+uppercase letters, digits, and the underscore
+.Pq Ql _
+character.
+In the latter case, you can ignore the warnings
+.Po
+.Nm sudo
+will not complain
+.Pc .
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the undefined alias was used.
+In
+.Fl s
+(strict) mode these are errors, not warnings.
+.It Li Warning: unused {User,Runas,Host,Cmnd}_Alias
+The specified {User,Runas,Host,Cmnd}_Alias was defined but never
+used.
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the unused alias was defined.
+You may wish to comment out or remove the unused alias.
+.It Li Warning: cycle in {User,Runas,Host,Cmnd}_Alias
+The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
+itself, either directly or through an alias it includes.
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the cycle was detected.
+This is only a warning unless
+.Nm
+is run in
+.Fl s
+(strict) mode as
+.Nm sudo
+will ignore cycles when parsing
+the
+.Em sudoers
+file.
+.It Li unknown defaults entry \&"name\&"
+The
+.Em sudoers
+file contains a
+.Li Defaults
+setting not recognized by
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr vipw @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS file in the
+.Nm sudo
+distribution (https://www.sudo.ws/contributors.html) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+There is no easy way to prevent a user from gaining a root shell if
+the editor used by
+.Nm
+allows shell escapes.
+.Sh BUGS
+If you feel you have found a bug in
+.Nm ,
+please submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE file distributed with
+.Nm sudo
+or https://www.sudo.ws/license.html for complete details.