SUDO.CONF(5)
๐ sudo.conf(5) ๐
File Formats Manual ๐ฆ
๐ NAME ๐
okay so sudo.conf โ configuration for the sudo front-end โจ
๐ธ DESCRIPTION ๐ธ
bestie, the sudo.conf file is where you set up the sudo front-end ๐
You use it to configure sudo plugins, plugin-agnostic path names, debug flags, and other settings. it's giving control ๐
The sudo.conf file supports the following directives, which we'll go through in detail below:
Pluginโ an approval, audit, I/O logging, or security policy plugin ๐Pathโ a plugin-agnostic path ๐ฃ๏ธSetโ a front-end setting, likedisable_coredumporgroup_source๐๏ธDebugโ debug flags to help you debug sudo, sudoreplay, visudo, and the sudoers plugin ๐
The pound sign (#) marks a comment ๐ฌ The comment character and anything after it, up to the end of the line, get ignored. literally invisible to sudo ๐
Got a long line? You can continue it with a backslash (\) as the very last character on the line ๐งต Leading white space is stripped from the start of lines even when you use a continuation character, so indent away ๐ซถ
Any non-comment line that doesn't start with Plugin, Path, Debug, or Set is silently ignored. no error, no drama, just vibes ๐ซ
The sudo.conf file is always parsed in the C locale ๐
๐ง Plugin configuration ๐ง
okay this part is so cool โจ sudo has a plugin architecture for security policies and input/output logging, which means third parties can build and distribute their own policy and I/O logging plugins that work seamlessly with the sudo front-end ๐ฆ Plugins get dynamically loaded based on what's in sudo.conf ๐
A Plugin line is the Plugin keyword, followed by the symbol_name and the path to the dynamic shared object that holds the plugin. The symbol_name is the name of the struct approval_plugin, struct audit_plugin, struct io_plugin, or struct policy_plugin defined by the plugin. If a plugin implements multiple plugin types, you need a Plugin line for each unique symbol name ๐ The path can be fully qualified or relative. If it isn't fully qualified, it's relative to the directory set by the plugin_dir Path setting, which defaults to /usr/libexec/sudo. In other words:
Plugin sudoers_policy sudoers.so
is equivalent to:
Plugin sudoers_policy /usr/libexec/sudo/sudoers.so
If the plugin was compiled statically into the sudo binary instead of being installed as a dynamic shared object, you should specify the path without a leading directory, since it doesn't actually exist in the file system ๐ง For example:
Plugin sudoers_policy sudoers.so
On AIX systems, the plugin can be either a shared object ending in .so, or an archive file containing a shared object ending in .a with the name of the shared object in parentheses at the end ๐ค
Starting with sudo 1.8.5, any extra parameters after the path get passed as arguments to the plugin's open function โจ For example, to override the compile-time default sudoers file mode:
Plugin sudoers_policy sudoers.so sudoers_mode=0440
See the sudoers(5) manual for a list of supported arguments ๐
The same dynamic shared object can contain multiple plugins, each with a different symbol name ๐
The file must be owned by user-ID 0 and only writable by its owner. Because of the ambiguities that come up with composite policies, only a single policy plugin may be specified. This limitation does not apply to I/O plugins ๐
โโ๏ธ
โ ๏ธ Heads up: if there's nosudo.conffile at all, or it has noPluginlines, the sudoers plugin is used as the default security policy, for I/O logging (if the policy enables it), and for auditing. It's equivalent to this:Plugin sudoers_policy sudoers.so Plugin sudoers_io sudoers.so Plugin sudoers_audit sudoers.so
Starting with sudo version 1.9.1, some of the logging functionality of the sudoers plugin moved from the policy plugin to an audit plugin ๐ To keep things compatible with sudo.conf files from older sudo versions, if sudoers is configured as the security policy, it'll be used as an audit plugin too. This guarantees the logging behavior matches sudo versions 1.9.0 and below. so consistent, no cap ๐ซถ
For more on the sudo plugin architecture, check out the sudo_plugin(5) manual ๐ฆ
๐ฃ๏ธ Path settings ๐ฃ๏ธ
A Path line is the Path keyword, followed by the name of the path you want to set and its value. For example:
Path intercept /usr/libexec/sudo/sudo_intercept.so
Path noexec /usr/libexec/sudo/sudo_noexec.so
Path askpass /usr/bin/ssh-askpass
If you don't specify a path name, features that rely on that setting get disabled ๐ Disabling Path settings is only supported in sudo version 1.8.16 and higher.
The following plugin-agnostic paths can be set in the /etc/sudo.conf file ๐
askpass : The fully-qualified path to a helper program that reads the user's password when no terminal is available ๐ That can happen when sudo runs from a graphical app instead of a text-based one. The program set by askpass should display the argument passed to it as the prompt and write the user's password to standard output. The SUDO_ASKPASS environment variable can override the value of askpass โจ
devsearch : An ordered, colon-separated search path of directories to look in for device nodes ๐ This gets used when mapping the process's tty device number to a device name on systems that don't provide another way to do that. Sudo will not recurse into sub-directories. So if terminal devices live in a sub-directory of /dev, that path has to be explicitly listed in devsearch ๐ซ The default value is /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
This option is ignored on systems that support either the devname() or _ttyname_dev() functions, for example BSD, macOS, and Solaris ๐
intercept : The path to a shared library full of wrappers for the execve(2), execl(3), execle(3), execlp(3), execv(3), execvp(3), execvpe(3), and system(3) library functions ๐ต๏ธโโ๏ธ These wrappers intercept attempts to run further commands and do a policy check before letting them execute. This is how the intercept and log_subcmds functionality works on systems that support LD_PRELOAD or the equivalent.
The intercept path can be set to a single fully-qualified path or, on systems that support separate LD_PRELOAD environment variables for 32-bit and 64-bit executables, it can optionally be set to two fully-qualified paths separated by a colon (:). The first path should be the 32-bit version and the second the 64-bit version. This two-path form is currently only supported on AIX and Solaris systems. The default value is /usr/libexec/sudo/sudo_intercept.so.
noexec : The path to a shared library full of wrappers for the execve(2), execl(3), execle(3), execlp(3), exect(3), execv(3), execveat(3), execvP(3), execvp(3), execvpe(3), fexecve(3), popen(3), posix_spawn(3), posix_spawnp(3), system(3), and wordexp(3) library functions ๐ซ These wrappers stop further commands from executing. This is how the noexec functionality works on systems that support LD_PRELOAD or the equivalent.
The noexec path can be set to a single fully-qualified path or, on systems that support separate LD_PRELOAD environment variables for 32-bit and 64-bit executables, it can optionally be set to two fully-qualified paths separated by a colon (:). The first path should be the 32-bit version and the second the 64-bit version. This two-path form is currently only supported on AIX and Solaris systems. The default value is /usr/libexec/sudo/sudo_noexec.so.
plugin_dir : The default directory to search when looking for plugins that are specified without a fully-qualified path name ๐ The default value is /usr/libexec/sudo.
sesh : The fully-qualified path to the sesh binary ๐ This setting is only used when sudo is built with SELinux support. The default value is /usr/libexec/sudo/sesh.
to be continued in part 2 ๐ โจ
dynamic Always ask the group database directly. ๐ It's "dynamic" because any changes made to the group database after the user logs in will show up in the group list. โจ On some systems, looking up all of a user's groups can take forever when the group database lives on the network ๐ฅฒ, but most operating systems have an efficient way to do these queries. Right now sudo supports efficient group queries on AIX, BSD, Linux, macOS, and Solaris. ๐ธ This is the default on macOS in sudo 1.9.6 and higher.
adaptive Only query the group database if the static group list the kernel gives back is maxed out (it has the maximum number of entries). ๐ง This is the default on everything except macOS in sudo 1.8.7 and higher.
For example, if you want sudo to only use the kernel's static list of groups for the user:
Set group_source static
This setting is only available in sudo version 1.8.7 and higher. ๐ซถ
๐ข max_groups ๐ข
The maximum number of user groups sudo will retrieve from the group database. ๐ Values less than one or larger than 1024 get ignored, so don't try it, bestie. ๐ This only matters when sudo is querying the group database directly. It's meant for systems where there's no way to detect when the array that gets filled with group entries is too small. By default, sudo allocates four times the system's maximum number of groups (see above), and if the group database query fails, it retries with double that number.
This setting is only available in sudo version 1.8.7 and higher. It shouldn't be needed in sudo versions 1.8.24 and higher, and it may be removed in a later release. ๐
๐ probe_interfaces ๐
By default, sudo probes the system's network interfaces and hands the IP address of each enabled interface to the policy plugin. ๐ฆ This lets the plugin match rules by IP address without having to query DNS, which is so smart. On Linux systems with a huge number of virtual interfaces, this can take a non-negligible amount of time. โณ If you don't need IP-based matching, you can turn off the interface probing like this:
Set probe_interfaces false
This setting is only available in sudo version 1.8.10 and higher. ๐
๐ Debug settings ๐
sudo versions 1.8.4 and higher come with a flexible debugging framework that can log what sudo is doing internally when something goes wrong. ๐ต๏ธโโ๏ธ It's giving detective energy.
A Debug line is made up of the Debug keyword, then the name of the program, plugin, or shared object you want to debug, then the debug file name, and finally a comma-separated list of debug flags. The debug flag syntax used by sudo, the sudoers plugin, and its associated programs and shared objects is subsystem@priority. Third-party plugins are free to use a different format, as long as it doesn't include a comma (,). ๐
On AIX systems, a Debug line will match a plugin specified as any of these: the name of an SVR4-style shared object file ending in .so, an archive file ending in .a, or an archive file ending in .a with the name of the shared object in parentheses. ๐
Examples:
Debug sudo /var/log/sudo_debug all@warn,plugin@info
This would log all debugging statements at the warn level and higher, plus the ones at the info level for the plugin subsystem. ๐
Debug sudo_intercept.so /var/log/intercept_debug all@debug
This would log all debugging statements, no matter the level, for the sudo_intercept.so shared library, which implements sudo's intercept functionality on some systems. ๐
Debug sudoers.so /var/log/sudoers_debug all@debug
This would log all debugging statements, no matter the level, for the sudoers plugin. โจ Check out sudoers(5) for the full list of subsystems the sudoers plugin supports. ๐
As of sudo 1.8.12, you can specify multiple Debug entries per program. Older versions of sudo only supported a single Debug entry per program, so bestie, that's a glow up. ๐ฆ Plugin-specific Debug entries are also supported starting with sudo 1.8.12, and they're matched either by the base name of the loaded plugin (for example sudoers.so) or by the plugin's fully-qualified path name. Before that, the sudoers plugin shared the same Debug entry as the sudo front-end and couldn't be configured separately. ๐ญ
The following priorities are supported, in order of decreasing severity: crit, err, warn, notice, diag, info, trace, and debug. Each priority, when specified, also includes every priority higher than it. For example, a priority of notice includes debug messages logged at notice and higher. ๐
The trace and debug priorities also include function call tracing, which logs when a function is entered and when it returns. ๐ฐ๏ธ For example, here's a trace for the get_user_groups() function, located in src/sudo.c:
sudo[123] -> get_user_groups @ src/sudo.c:385
sudo[123] <- get_user_groups @ src/sudo.c:429 := groups=10,0,5
When the function is entered, marked by a right arrow ->, the program, process ID, function, source file, and line number get logged. When the function returns, marked by a left arrow <-, the same info gets logged along with the return value. In this case, the return value is a string. ๐งต
The following subsystems are used by the sudo front-end:
allโ matches every subsystem ๐argsโ command line argument processing ๐งพconvโ user conversation ๐ฌeditโ sudoedit โ๏ธeventโ event subsystem ๐execโ command execution ๐mainโ sudo main function ๐netifโ network interface handling ๐pcommโ communication with the plugin ๐กpluginโ plugin configuration ๐ptyโ pseudo-terminal related code ๐ฅ๏ธselinuxโ SELinux-specific handling ๐ก๏ธutilโ utility functions ๐งฐutmpโ utmp handling ๐ชช
The sudoers(5) plugin includes support for additional subsystems, so go check those out too. ๐
๐ FILES ๐
/etc/sudo.confโ sudo front-end configuration ๐
โจ EXAMPLES โจ
okay, here's the default /etc/sudo.conf file, and it's honestly a whole vibe ๐
every line starting with # is a comment, so nothing happens until you uncomment it ๐
#
# Default /etc/sudo.conf file
#
# Sudo plugins:
# Plugin plugin_name plugin_path plugin_options ...
#
# The plugin_path is relative to /usr/libexec/sudo 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
Okay so the Plugin lines are how you pick your plugins ๐ The plugin_path is relative to /usr/libexec/sudo unless you write out the full path, and the plugin_name has to match a global symbol inside the plugin that holds its interface structure. The plugin_options part is totally optional โจ And if you don't have any Plugin lines at all, sudo quietly falls back to the sudoers plugin, which is super iconic of it ๐
#
# 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/bin/ssh-askpass
#
# Use the Gnome OpenSSH askpass
#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
For the askpass helper ๐ซถ you can point it at a program that gives you a graphical password prompt for sudo -A. Sudo doesn't come with its own askpass program, but it can totally borrow the OpenSSH one, so you can pick /usr/bin/ssh-askpass or the Gnome flavour at /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
The devsearch path is a colon-separated list of places sudo checks when it's hunting for a user's terminal device ๐ Think of it as a little scavenger hunt through /dev ๐ฆ
#
# Sudo command interception:
# Path intercept /path/to/sudo_intercept.so
#
# Path to a shared library containing replacements for the execv(),
# execve() and fexecve() library functions, which perform a policy
# check to verify whether the command is allowed and simply return
# an error if it is not. This is used to implement the "intercept"
# 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_intercept.so file.
#
#Path intercept /usr/libexec/sudo/sudo_intercept.so
Next up is intercept ๐ง This is a shared library full of replacement versions of execv(), execve() and fexecve(). Each one runs a policy check first to see if the command is allowed, and if it isn't, it just returns an error. It's how the "intercept" feature works on systems that support LD_PRELOAD or something equivalent ๐ The built-in path is usually fine, so only change it if you rename or move sudo_intercept.so ๐
#
# Sudo noexec:
# Path noexec /path/to/sudo_noexec.so
#
# Path to a shared library containing replacements for the execv()
# family of 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 /usr/libexec/sudo/sudo_noexec.so
Same energy for noexec ๐ This shared library has replacements for the execv() family that simply return an error. It's how the "noexec" functionality works on systems with LD_PRELOAD or its equivalent. Again, the compiled-in value is usually perfect, so only touch it if you rename or move 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 /usr/libexec/sudo
The plugin_dir is the default folder sudo searches when a plugin is listed without a fully-qualified path ๐ The example shows /usr/libexec/sudo, which is the classic spot ๐
#
# 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
Core dumps are next ๐ธ By default, sudo turns core dumps off while it's running, and they get turned back on for the command that sudo runs. If you're debugging a sudo problem, you can set disable_coredump to false so core dumps stay on ๐ซถ
#
# 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
Now the group_source setting ๐ Sudo hands the user's group list to the policy plugin. If the user is in the maximum number of groups (usually 16), sudo asks the group database directly so the full list makes it through. That can be pricey on some systems, which is why it's configurable. You've got three choices:
staticโ use the user's group list returned by the kerneldynamicโ query the group database for the list of groups every timeadaptiveโ if the user is in fewer than the maximum number of groups, use the kernel list, otherwise query the group database
The example uses 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
probe_interfaces is up next ๐ฆ By default, sudo checks the system's network interfaces and passes the IP address of every enabled one to the policy plugin. If you have tons of virtual interfaces, this can take a noticeable amount of time, so you can turn it off with 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
Last but not least, Debug lines ๐ Sudo and its friends can log debug info to a file. The program is usually sudo, sudoers.so, sudoreplay or visudo. Subsystems depend on the program, and all matches every one of them. Priorities can be crit, err, warn, notice, diag, info, trace or debug, and you can stack several subsystem@priority pairs with a comma between them ๐ง
โจ SEE ALSO โจ
Check out sudo_plugin(5), sudoers(5) and sudo(8) for more of the good stuff ๐
โจ AUTHORS โจ
Lots of people have worked on sudo over the years ๐ซถ This version is mostly code written by:
Todd C. Miller
Want the full list of everyone who's helped out? See the CONTRIBUTORS.md file in the sudo distribution, at https://www.sudo.ws/about/contributors/ ๐
โจ BUGS โจ
Think you found a bug in sudo.conf? ๐ You can file a report in the sudo bug database at https://bugzilla.sudo.ws/, or open an issue at https://github.com/sudo-project/sudo/issues. If email is more your thing, you can send messages to the sudo-workers mailing list at https://www.sudo.ws/mailman/listinfo/sudo-workers (public) or to <sudo@sudo.ws> (private).
Please, please do NOT report security vulnerabilities through public GitHub issues, Bugzilla or mailing lists ๐ญ Instead, email them to<Todd.Miller@sudo.ws>. You can encrypt your message with PGP if you want, using the key athttps://www.sudo.ws/dist/PGPKEYS.
โจ SUPPORT โจ
There's limited free support through the sudo-users mailing list ๐ To subscribe or search the archives, head to https://www.sudo.ws/mailman/listinfo/sudo-users.
โจ DISCLAIMER โจ
sudo comes "AS IS", so any express or implied warranties, including the implied warranties of merchantability and fitness for a particular purpose, are disclaimed ๐ For the full details, check the LICENSE.md file that ships with sudo, or visit https://www.sudo.ws/about/license/.
And that's a wrap on SUDO.CONF(5) ๐ Sudo 1.9.17p2, dated November 6, 2023, and you're officially a sudo.conf expert now ๐ โจ bestie, you did amazing ๐ซถ๐
๐ฆ where this page comes from
- ubuntu questing: sudo 1.9.17p2-1ubuntu1
- ubuntu questing: sudo 1.9.17p2-1ubuntu1.1 ยท ISC
- ubuntu resolute: sudo 1.9.17p2-1ubuntu3 ยท ISC
- ubuntu resolute: sudo 1.9.17p2-1ubuntu3.2 ยท ISC
- ubuntu stonking: sudo 1.9.17p2-7ubuntu5 ยท ISC
- ๐ the page's license: ISC
- Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
- ๐ girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms