From 83dab3b7ab098ba1c093964e7ff862f287c8a12c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 15 Jul 2009 00:48:52 -0600 Subject: [PATCH] Imported Upstream version 1.7.2 --- ChangeLog | 585 ++++++++- INSTALL | 15 + LICENSE | 30 +- Makefile.in | 71 +- README | 2 +- TROUBLESHOOTING | 8 + WHATSNEW | 74 ++ aclocal.m4 | 42 +- alias.c | 25 +- audit.c | 76 ++ auth/aix_auth.c | 6 +- auth/pam.c | 6 +- auth/sudo_auth.c | 37 +- auth/sudo_auth.h | 4 +- bsm_audit.c | 173 +++ version.h => bsm_audit.h | 18 +- check.c | 24 +- config.h.in | 48 + configure | 1187 +++++++++++++----- configure.in | 315 +++-- def_data.c | 12 + def_data.h | 6 + def_data.in | 9 + env.c | 395 ++++-- fileops.c | 8 +- glob.c | 5 +- gram.c | 9 +- gram.y | 7 +- interfaces.c | 16 +- lbuf.c | 11 +- ldap.c | 71 +- logging.c | 10 +- logging.h | 6 +- match.c | 290 +++-- nonunix.h | 46 + parse.c | 16 +- parse.h | 11 +- pathnames.h.in | 8 +- pwutil.c | 32 +- redblack.c | 24 +- set_perms.c | 92 +- sudo.c | 164 ++- sudo.cat | 206 ++-- sudo.h | 18 +- sudo.man.in | 67 +- sudo.pod | 61 +- sudo_nss.c | 92 +- sudo_nss.h | 7 +- sudo_usage.h.in | 29 +- sudoers.cat | 668 ++++++---- sudoers.ldap.cat | 248 ++-- sudoers.ldap.man.in | 100 +- sudoers.ldap.pod | 65 +- sudoers.man.in | 168 ++- sudoers.pod | 179 ++- term.c | 180 +++ testsudoers.c | 11 +- tgetpass.c | 128 +- toke.c | 2500 +++++++++++++++++++++----------------- toke.l | 406 ++++++- vasgroups.c | 323 +++++ visudo.c | 147 ++- visudo.cat | 22 +- visudo.man.in | 14 +- 64 files changed, 6813 insertions(+), 2820 deletions(-) create mode 100644 audit.c create mode 100644 bsm_audit.c rename version.h => bsm_audit.h (61%) create mode 100644 nonunix.h create mode 100644 term.c create mode 100644 vasgroups.c diff --git a/ChangeLog b/ChangeLog index 63023fc..5c61070 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,586 @@ +2009-06-30 08:41 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Add missing single + quotes around a colon in Runas_Spec definition. From Elias + Benali. + +2009-06-29 09:36 millert + + * redblack.c: In rbrepair, re-color the root or the first non-block + node we find to be black. Re-coloring the root is probably not + needed but won't hurt. + +2009-06-29 09:35 millert + + * sudo.cat, sudoers.cat, sudo.man.in, sudoers.man.in: regen + +2009-06-26 16:40 millert + + * redblack.c: When repairing the tree, don't touch the root node. + +2009-06-25 08:44 millert + + * set_perms.c: Protect call to setegid in runas_setup with #ifdef + HAVE_SETEUID. Reported by Josef Schmid. + +2009-06-23 14:29 millert + + * sudoers.pod: Document that we accept env_pam-style environment + files + +2009-06-23 14:24 millert + + * env.c: Adapt to accept pam_env-style /etc/environment which + allows shell-style lines such as: export EDITOR="/usr/bin/vi" + +2009-06-23 12:22 millert + + * sudoers.pod: Make it clear that env_delete only works when + !env_reset. From Loïc Minier + +2009-06-15 17:19 millert + + * sudo.pod, sudoers.pod: Add non-unix group bits, adapted from + Quest + +2009-06-15 17:18 millert + + * Makefile.in: build the .cat page in the current working dir, not + the src dir + +2009-06-15 09:10 millert + + * env.c: Return EINVAL in setenv() if var is NULL or the empty + string to match glibc behavior. + +2009-06-13 16:52 millert + + * configure, configure.in: Use AS_HELP_STRING for AC_ARG_WITH and + AC_ARG_ENABLE + +2009-06-11 16:29 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: + regen + +2009-06-09 10:08 millert + + * INSTALL: Document --with-libvas and --with-libvas-rpath + +2009-05-29 09:43 millert + + * ldap.c, sudoers.ldap.pod: For netscape-derived LDAP SDKs the cert + and key paths may be a directory or a file. However, version 5.0 + of the SDK only seems to support using a directory. If + ldapssl_clientauth_init fails and the cert or key paths look like + they could be files, strip off the last path element and try + again. + +2009-05-29 09:40 millert + + * Makefile.in: Add non-Unix group .o to COMMON_OBJS and substitute + in path to flex. + +2009-05-26 20:49 millert + + * configure, configure.in, match.c, sudo.c, vasgroups.c: Update + non-Unix group support from Quest, as reworked by me. + +2009-05-26 20:47 millert + + * toke.c: regen + +2009-05-26 20:46 millert + + * toke.l: Add support for escaped hex chars in names, e.g. \x20 for + space. + +2009-05-25 08:02 millert + + * LICENSE, Makefile.in, aclocal.m4, alias.c, check.c, env.c, + fileops.c, glob.c, gram.y, interfaces.c, lbuf.c, ldap.c, + logging.c, logging.h, match.c, parse.c, parse.h, pathnames.h.in, + pwutil.c, set_perms.c, sudo.c, sudo.h, sudo.pod, sudo_nss.c, + sudo_nss.h, sudo_usage.h.in, sudoers.ldap.pod, sudoers.pod, + testsudoers.c, tgetpass.c, toke.l, visudo.c, auth/aix_auth.c, + auth/pam.c, auth/sudo_auth.c, auth/sudo_auth.h: Update copyright + years. + +2009-05-24 08:33 millert + + * interfaces.c, lbuf.c: Minor fixes for Minix-3 + +2009-05-22 06:37 millert + + * set_perms.c: Handle getgroups() returning 0. Also add missing + check for HAVE_GETGROUPS. + +2009-05-19 17:24 millert + + * Makefile.in, config.h.in, configure, configure.in, sudo.c, + version.h, visudo.c: Replace version.h with PACKAGE_VERSION set + via AC_INIT in configure. + +2009-05-18 06:33 millert + + * set_perms.c: Remove group setting code in setusercontext case, we + will do it ourselves later on in runas_setup. Set the gid after + initgroups/setgroups is called, since on Mac OS X it seems to + change the egid. + +2009-05-17 18:19 millert + + * LICENSE, Makefile.in, config.h.in, match.c, nonunix.h, sudo.c, + vasgroups.c: Initial bits of non-unix group support using Quest + Authentication Services + +2009-05-17 16:52 millert + + * toke.c, toke.l: Accept %:foo as a non-Unix group + +2009-05-17 16:22 millert + + * toke.c, toke.l: Allow user/group to be double quoted in the case + of non-Unix groups which contain spaces. + +2009-05-11 12:47 millert + + * match.c: Don't allow the user to specify the default runas user + if their sudoers entry only allows them to run as a group. + +2009-05-10 07:59 millert + + * sudo.c: Must call audit_success before we change uids. + +2009-05-10 07:52 millert + + * logging.c, set_perms.c, sudo.h, testsudoers.c: Add option for + set_perm to not exit on failure and use this in the logging + routines. + +2009-05-10 07:33 millert + + * parse.c: In -l mode, if the user is only allowed to run as a + group, display the user's name, not root's before the allowed + group. + +2009-05-09 21:00 millert + + * sudo.c: Fix -g mode, broken by rev 1.503 which had the side + effect of setting the runas user to root unilaterally. + +2009-05-08 16:19 millert + + * fileops.c: When unlocking a file with fcntl, use F_SETLK, not + F_SETLKW. + +2009-05-08 13:07 millert + + * pwutil.c: Only cache by the method we fetched for pwd and grp + lookups. Previously we cached both by namd and id but this can + cause problems for entries that share the same id. Also add more + info in the error message in case the insert fails (which should + now be impossible). + +2009-04-30 15:04 millert + + * sudoers.pod: Add a clarification from Nick Sieger + +2009-04-25 12:49 millert + + * env.c: Inline the setting of the environment string. + +2009-04-24 14:53 millert + + * env.c: setenv(3) in Linux treats a NUL value as the empty string + setenv(3) in BSD doesn't return an error if the name has '=' in + it, it just treats the '=' as end of string. + +2009-04-22 16:32 millert + + * toke.c, toke.l: Not all systems have d_namlen + +2009-04-20 13:53 millert + + * sudoers.pod: Fix up some pod2html issues. + +2009-04-19 14:09 millert + + * interfaces.c: Check for NULL ifa_addr and ifa_netmask. Adapted + from a diff from Quest Software. + +2009-04-19 09:01 millert + + * sudoers.pod: Ignore files ending in '~' in sudo.d (emacs backup + files) + +2009-04-19 08:56 millert + + * toke.c, toke.l: Ignore files ending in '~' in sudo.d (emacs + backup files) + +2009-04-18 19:37 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod, toke.c, toke.l: For + #includedir, ignore any file containing a dot + +2009-04-18 19:25 millert + + * Makefile.in, version.h: Bump version + +2009-04-18 19:25 millert + + * gram.c, gram.y, parse.c, parse.h, sudo.c, sudo.h, sudoers.cat, + sudoers.man.in, sudoers.pod, testsudoers.c, toke.c, toke.l, + visudo.c: Implement #includedir directive. Files in an + includedir are not edited by visudo unless they contain a syntax + error. + +2009-04-18 12:06 millert + + * ChangeLog: sync + +2009-04-18 10:27 millert + + * WHATSNEW: Forgot umask_override + +2009-04-18 09:25 millert + + * ChangeLog, TODO: sync + +2009-04-16 08:22 millert + + * visudo.c: Rewind stream if we fdopen sudoers since it may not be + at the beginning. Set the keepopen flag on already-open files + too so the lexer doesn't close them out from under us. + +2009-04-16 08:18 millert + + * visudo.c: Print the proper file name when there is a parse error + in an include file. + +2009-04-11 07:45 millert + + * WHATSNEW: Sync + +2009-04-10 16:59 millert + + * configure, configure.in: Fix a warning when --without-ldap is + specified. + +2009-04-05 12:25 millert + + * alias.c, parse.h, visudo.c: Store aliases that we remove during + check_aliases in a freelist and free them at the end so we don't + leak memory. + +2009-03-28 09:30 millert + + * visudo.c: Check aliases in -c mode too. + +2009-03-28 09:09 millert + + * alias.c, parse.h, visudo.c: Make alias_remove return the alias + struct instead of freeing it directly. Fixes a use after free in + alias_remove_recursive, the only consumer. + +2009-03-28 09:07 millert + + * alias.c, match.c, parse.c, parse.h, visudo.c: Rename find_alias + -> alias_find for consistency. + +2009-03-27 19:29 millert + + * visudo.c: When checking for unused aliases, recurse if the alias + points to another alias. + +2009-03-16 12:11 millert + + * ldap.c: Back out rev 1.105 for now. Real ldapux_client.conf + support will be done later after some refactoring. + +2009-03-14 12:02 millert + + * ldap.c: Treat ldap_hostport the same as "host" for ldapux. + +2009-03-13 21:04 millert + + * configure, configure.in: Only check for + ldap_sasl_interactive_bind_s if we can find sasl.h. Fixes + compilation with ldapux. + +2009-03-11 20:03 millert + + * fileops.c: fix char subscript + +2009-03-11 19:19 millert + + * Makefile.in: remove errant carriage returns + +2009-03-11 19:01 millert + + * audit.c, env.c: fix K&R compilation + +2009-03-11 12:12 millert + + * sudo.man.in, sudo.cat, sudoers.cat, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: + regen + +2009-03-10 17:34 millert + + * config.h.in: Add missing HAVE_BSM_AUDIT + +2009-03-10 17:21 millert + + * WHATSNEW: Add 1.7.1 features + +2009-03-10 17:10 millert + + * INSTALL: Mention --with-netsvc + +2009-03-10 17:08 millert + + * sudoers.ldap.pod: Document netsvc.conf support + +2009-03-10 16:44 millert + + * configure, configure.in, pathnames.h.in, sudo.c, sudo_nss.c, + sudo_nss.h: Add support for AIX netsvc.conf (like nsswitch.conf). + +2009-03-08 16:57 millert + + * configure, config.h.in, configure.in, env.c: Add + --enable-env-debug flag to enable environment sanity checks. + +2009-03-08 11:51 millert + + * sudoers.ldap.pod, sudoers.pod: Work around some pod2html issue. + +2009-03-07 17:10 millert + + * env.c: Only sync environ for putenv, setenv, and unsetenv. We + need to make sure that sudo_putenv and sudo_setenv only modify + env.envp, not environ. + +2009-03-02 14:19 millert + + * env.c: Really fix UNSETENV_VOID + +2009-03-02 14:18 millert + + * env.c: Fix unsetenv when UNSETENV_VOID + +2009-03-02 08:00 millert + + * aclocal.m4, configure: Fix SUDO_FUNC_PUTENV_CONST + +2009-03-02 07:36 millert + + * ldap.c: tivoli-based ldap does not have ldapssl_err2string + +2009-03-02 07:30 millert + + * configure: regen + +2009-03-01 16:20 millert + + * config.h.in, configure, configure.in, ldap.c: Add support for + Tivoli-based LDAP start TLS as seen in AIX. Untested. + +2009-03-01 08:52 millert + + * env.c: Add sanity checks for setenv/unsetenv + +2009-02-28 20:17 millert + + * Makefile.in: Include bsm_audit.h in the tarball + +2009-02-28 20:00 millert + + * Makefile.in, version.h: bump version for sudo 1.7.1 + +2009-02-28 19:58 millert + + * aclocal.m4, config.h.in, configure, configure.in, env.c, ldap.c, + sudo.h, auth/aix_auth.c: Replace sudo_setenv/sudo_unsetenv with + calls to setenv/unsetenv and provide our own + setenv/unsetenv/putenv that operates on own env pointer. Make + sync_env() inline in setenv/unsetenv/putenv functions. + +2009-02-25 07:33 millert + + * sudo.c: Make "sudoedit -h" work as expected + +2009-02-25 07:21 millert + + * auth/pam.c: Make sure def_prompt is always defined. This is a + workaround for pam configs that prompt for a password in the + session but don't have an auth line. A better fix is to expand + the sudo prompt earlier and set def_prompt to that when + initializing. + +2009-02-25 06:17 millert + + * sudo.pod: Mention that the helper for -A may be graphical. + +2009-02-25 06:16 millert + + * TROUBLESHOOTING: Document what happens if there is no tty. + +2009-02-25 06:05 millert + + * sudo.c: cosmetic changes + +2009-02-25 05:47 millert + + * term.c: Fix term_restore + +2009-02-24 20:23 millert + + * sudo.c: Fix "sudo -k" with no other args + +2009-02-24 08:04 millert + + * check.c, sudo.c, sudo.pod, sudo_usage.h.in: Allow the -k flag to + be specified in conjunction with a command or another option that + may require authentication. + +2009-02-23 09:18 millert + + * configure, configure.in: Remove unneeded AC_CANONICAL_TARGET; + from Diego E. 'Flameeyes' + +2009-02-23 09:15 millert + + * Makefile.in: Parallel make fix. From Diego E. 'Flameeyes' + +2009-02-21 17:03 millert + + * def_data.c, def_data.h, def_data.in, sudo.c, sudoers.pod: + Implement umask_override + +2009-02-21 16:51 millert + + * toke.c: regen + +2009-02-21 16:49 millert + + * sudoers.pod, toke.l, visudo.c: Implement %h escape in sudoers + include filenames. + +2009-02-21 08:43 millert + + * audit.c: Need to include compat.h + +2009-02-21 08:37 millert + + * Makefile.in, audit.c, bsm_audit.c, bsm_audit.h, logging.h, + sudo.c: Make audit_success and audit_failure generic functions in + preparation for integrating linux audit support. + +2009-02-21 08:06 millert + + * term.c: remove duplicate include + +2009-02-20 16:13 millert + + * bsm_audit.c: Add missing include + +2009-02-20 15:55 millert + + * sudo.c: May need to update the runas user after parsing + command-based defaults. + +2009-02-18 10:53 millert + + * glob.c: Add missing pair of braces introduced with character + class support. + +2009-02-15 15:53 millert + + * def_data.c, def_data.h, def_data.in, sudoers.pod, tgetpass.c: + Rename pwstars to pwfeedback + +2009-02-10 20:25 millert + + * bsm_audit.c, bsm_audit.h: Add const to make MacOS happy. + +2009-02-10 20:18 millert + + * Makefile.in, bsm_audit.c, bsm_audit.h, configure, configure.in, + sudo.c, auth/sudo_auth.c: Add bsm audit support from Christian + S.J. Peron + +2009-02-10 19:58 millert + + * term.c: This is new code, no DARPA notice. + +2009-02-10 14:04 millert + + * def_data.c, def_data.h, def_data.in, match.c, sudoers.pod: Rename + simple_glob -> fast_glob + +2009-02-10 09:39 millert + + * match.c: g/c unused var + +2009-02-10 08:09 millert + + * def_data.c, def_data.h, def_data.in, match.c, sudoers.pod: Add + simple_glob option to use fnmatch() instead of glob(). This is + useful when you need to specify patterns that reference network + file systems. + +2009-02-10 07:58 millert + + * tgetpass.c: add term_* proto + +2009-02-10 07:51 millert + + * sudoers.pod: mention glob() + +2009-02-09 07:59 millert + + * tgetpass.c: Delete any pwstars we wrote after the user hits + return. That way there is no record on screen as to the user's + password length. + +2009-02-08 10:27 millert + + * term.c: Move terminal setting bits from tgetpass.c to term.c + +2009-02-07 19:50 millert + + * Makefile.in, def_data.c, def_data.h, def_data.in, sudoers.pod, + tgetpass.c: Add pwstars sudoers option that causes sudo to print + a star every time the user presses a key. + +2009-02-03 10:10 millert + + * Makefile.in: Fix up F<> brokenness for visudo.man.in and + sudoers.ldap.man.in. + +2009-01-27 11:54 millert + + * ldap.c: For ldap_search_ext_s() the sizelimit param should be 0, + not -1, to indicate no limit. From Mark Janssen. + +2009-01-17 17:36 millert + + * toke.c, toke.l: Comments that begin with #- should not be parsed + as uids. + +2009-01-08 19:13 millert + + * sudo.c: Do not try to set the close on exec flag if we didn't + actually open sudoers. + +2008-12-19 12:40 millert + + * ChangeLog: regen + 2008-12-14 17:40 millert * TODO: sync @@ -4506,7 +5089,7 @@ 2004-10-01 10:58 millert * sample.pam, sample.sudoers, sample.syslog.conf, sudoers: Add - $Sudo: ChangeLog,v 1.19 2008/12/19 17:40:39 millert Exp $ tags. + $Sudo: ChangeLog,v 1.22 2009/07/12 01:12:29 millert Exp $ tags. 2004-10-01 10:47 millert diff --git a/INSTALL b/INSTALL index 2ffb8f2..b58852b 100644 --- a/INSTALL +++ b/INSTALL @@ -195,6 +195,11 @@ Special features/options: If nsswitch is disabled but LDAP is enabled, sudo will check LDAP first, then the sudoers file. + --with-netsvc[=filename] + Path to netsvc.conf or "no" to disable netsvc.conf support. + If specified, sudo uses this file instead of /etc/netsvc.conf + on AIX systems. + --with-aixauth Enable support for the AIX 4.x general authentication function. This will use the authentication scheme specified for the user @@ -330,6 +335,16 @@ Special features/options: Enable support for role based access control (RBAC) on systems that support SELinux. + --with-libvas=[NAME] + Enable non-Unix group support using Quest Authentication + Services. If NAME is specified, it should be the name of + the shared library providing QAS support (libvas.so by default). + + --with-libvas-rpath=[PATH] + The path to search when loading libvas.so (or an alternate + name as specified by --with-libvas). This option only has + an effect when --with-libvas is specified. + The following options are also configurable at runtime: --with-long-otp-prompt diff --git a/LICENSE b/LICENSE index 786b7a0..0632e0b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Sudo is distributed under the following ISC-style license: - Copyright (c) 1994-1996, 1998-2008 + Copyright (c) 1994-1996, 1998-2009 Todd C. Miller Permission to use, copy, modify, and distribute this software for any @@ -48,3 +48,31 @@ bear the following UCB license: 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. + +nonunix.h and vasgroups.c bear the following license: + + Copyright (c) 2006 Quest Software, 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: + + 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 Quest Software, 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 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/Makefile.in b/Makefile.in index c097af7..c7fc8d9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,5 +1,5 @@ # -# Copyright (c) 1996, 1998-2005, 2007-2008 +# Copyright (c) 1996, 1998-2005, 2007-2009 # Todd C. Miller # # Permission to use, copy, modify, and distribute this software for any @@ -21,7 +21,7 @@ # # @configure_input@ # -# $Sudo: Makefile.in,v 1.326 2008/12/03 20:40:47 millert Exp $ +# $Sudo: Makefile.in,v 1.340 2009/06/15 21:18:53 millert Exp $ # #### Start of system configuration section. #### @@ -33,7 +33,7 @@ top_builddir = . # Compiler & tools to use CC = @CC@ -LEX = flex +FLEX = @FLEX@ YACC = @YACC@ NROFF = nroff -Tascii LIBTOOL = @LIBTOOL@ @@ -102,36 +102,37 @@ SHELL = /bin/sh PROGS = @PROGS@ -SRCS = aix.c alias.c alloc.c check.c closefrom.c def_data.c defaults.c env.c \ - error.c fileops.c find_path.c fnmatch.c getcwd.c getprogname.c \ - getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y interfaces.c \ - isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c memrchr.c \ - parse.c pwutil.c set_perms.c sigaction.c snprintf.c strcasecmp.c \ - strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c sudo_edit.c \ - sudo_nss.c testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c utimes.c \ - visudo.c zero_bytes.c redblack.c selinux.c sesh.c $(AUTH_SRCS) +SRCS = aix.c alias.c alloc.c audit.c bsm_audit.c check.c closefrom.c \ + def_data.c defaults.c env.c error.c fileops.c find_path.c fnmatch.c \ + getcwd.c getprogname.c getspwuid.c gettime.c glob.c goodpath.c gram.c \ + gram.y interfaces.c isblank.c lbuf.c ldap.c list.c logging.c match.c \ + mkstemp.c memrchr.c parse.c pwutil.c set_perms.c sigaction.c \ + snprintf.c strcasecmp.c strerror.c strlcat.c strlcpy.c sudo.c \ + sudo_noexec.c sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c \ + toke.c toke.l tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \ + redblack.c selinux.c sesh.c $(AUTH_SRCS) AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \ auth/secureware.c auth/securid.c auth/securid5.c auth/sia.c \ auth/sudo_auth.c -HDRS = compat.h def_data.h defaults.h error.h ins_2001.h ins_classic.h \ - ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h list.h \ - logging.h parse.h sudo.h sudo_nss.h gram.h version.h auth/sudo_auth.h \ - emul/charclass.h emul/fnmatch.h emul/glob.h emul/timespec.h \ - emul/utime.h redblack.h +HDRS = bsm_audit.h compat.h def_data.h defaults.h error.h ins_2001.h \ + ins_classic.h ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h \ + list.h logging.h nonunix.h redblack.h parse.h sudo.h sudo_nss.h gram.h \ + auth/sudo_auth.h emul/charclass.h emul/fnmatch.h emul/glob.h \ + emul/timespec.h emul/utime.h AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ # Note: gram.o must come first here COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o list.o match.o \ - toke.o redblack.o zero_bytes.o + toke.o redblack.o zero_bytes.o @NONUNIX_GROUPS_IMPL@ -SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ check.o env.o \ +SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ audit.o check.o env.o \ getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ interfaces.o lbuf.o logging.o parse.o pwutil.o set_perms.o \ - sudo.o sudo_edit.o sudo_nss.o tgetpass.o + sudo.o sudo_edit.o sudo_nss.o term.o tgetpass.o VISUDO_OBJS = $(COMMON_OBJS) visudo.o fileops.o gettime.o goodpath.o \ find_path.o pwutil.o @@ -140,7 +141,7 @@ TEST_OBJS = $(COMMON_OBJS) interfaces.o testsudoers.o tsgetgrpw.o tspwutil.o LIB_OBJS = @LIBOBJS@ -VERSION = 1.7.0 +VERSION = @PACKAGE_VERSION@ DISTFILES = $(SRCS) $(HDRS) ChangeLog HISTORY INSTALL INSTALL.configure \ LICENSE Makefile.in PORTING README README.LDAP TROUBLESHOOTING \ @@ -181,8 +182,8 @@ all: $(PROGS) $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $< .man.cat: - @rm -f $(srcdir)/$@ - sed '1s/^/.if n .ll 78n/' $< | $(NROFF) -man > $(srcdir)/$@ + @rm -f $@ + sed '1s/^/.if n .ll 78n/' $< | $(NROFF) -man > $@ sudo: $(SUDO_OBJS) $(LIB_OBJS) $(CC) -o $@ $(SUDO_OBJS) $(LIB_OBJS) $(SUDO_LDFLAGS) $(SUDO_LIBS) @@ -211,7 +212,7 @@ $(devdir)/gram.c: $(srcdir)/gram.y # Uncomment the lines before -@true if you intend to modify toke.l $(devdir)/toke.c: $(srcdir)/toke.l -@DEV@ $(LEX) $(srcdir)/toke.l +@DEV@ $(FLEX) $(srcdir)/toke.l @DEV@ mv -f lex.yy.c toke.c -@true @@ -226,6 +227,10 @@ alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdi $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c alloc.o: $(srcdir)/alloc.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c +audit.o: $(srcdir)/audit.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/audit.c +bsm_audit.o: $(srcdir)/bsm_audit.c $(SUDODEP) bsm_audit.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/bsm_audit.c check.o: $(srcdir)/check.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c closefrom.o: $(srcdir)/closefrom.c config.h @@ -296,7 +301,7 @@ strlcpy.o: $(srcdir)/strlcpy.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcpy.c selinux.o: $(srcdir)/selinux.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/selinux.c -sudo.o: $(srcdir)/sudo.c $(SUDODEP) sudo_usage.h $(srcdir)/interfaces.h $(srcdir)/version.h +sudo.o: $(srcdir)/sudo.c $(SUDODEP) sudo_usage.h $(srcdir)/interfaces.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo.c sudo_edit.o: $(srcdir)/sudo_edit.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_edit.c @@ -304,6 +309,8 @@ sudo_noexec.o: $(srcdir)/sudo_noexec.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c sudo_nss.o: $(srcdir)/sudo_nss.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_nss.c +term.o: $(srcdir)/term.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/term.c testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) @@ -314,7 +321,9 @@ tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tsgetgrpw.c utimes.o: $(srcdir)/utimes.c $(srcdir)/compat.h $(srcdir)/emul/utime.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/utimes.c -visudo.o: $(srcdir)/visudo.c $(SUDODEP) $(srcdir)/version.h $(devdir)/gram.h +vasgroups.o: $(srcdir)/vasgroups.c $(srcdir)/nonunix.h $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/vasgroups.c +visudo.o: $(srcdir)/visudo.c $(SUDODEP) $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/visudo.c zero_bytes.o: $(srcdir)/zero_bytes.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/zero_bytes.c @@ -365,7 +374,7 @@ sudo.cat: sudo.man visudo.man.in: $(srcdir)/visudo.pod @rm -f $(srcdir)/$@ - ( cd $(srcdir); mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' visudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" visudo.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" >> $@ ) + ( cd $(srcdir); mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' visudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" visudo.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ ) visudo.man: visudo.man.in CONFIG_FILES=$@ CONFIG_HEADERS= sh ./config.status @@ -383,7 +392,7 @@ sudoers.cat: sudoers.man sudoers.ldap.man.in: $(srcdir)/sudoers.ldap.pod @rm -f $(srcdir)/$@ - ( cd $(srcdir); mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' sudoers.ldap.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" sudoers.ldap.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" >> $@ ) + ( cd $(srcdir); mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' sudoers.ldap.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" sudoers.ldap.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ ) sudoers.ldap.man:: sudoers.ldap.man.in CONFIG_FILES=$@ CONFIG_HEADERS= sh ./config.status @@ -407,22 +416,22 @@ install-dirs: $(DESTDIR)$(mandirsu) $(DESTDIR)$(mandirform) \ $(DESTDIR)$(noexecdir) -install-binaries: $(PROGS) +install-binaries: install-dirs $(PROGS) $(INSTALL) -O $(install_uid) -G $(install_gid) -M 4111 -s sudo $(DESTDIR)$(sudodir)/sudo rm -f $(DESTDIR)$(sudodir)/sudoedit ln $(DESTDIR)$(sudodir)/sudo $(DESTDIR)$(sudodir)/sudoedit $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0111 -s visudo $(DESTDIR)$(visudodir)/visudo @SELINUX@ $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0111 -s sesh $(DESTDIR)$(libexecdir)/sesh -install-noexec: sudo_noexec.la +install-noexec: install-dirs sudo_noexec.la test -f .libs/$(noexecfile) && $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0755 .libs/$(noexecfile) $(DESTDIR)$(noexecdir) -install-sudoers: +install-sudoers: install-dirs test -f $(DESTDIR)$(sudoersdir)/sudoers || \ $(INSTALL) -O $(sudoers_uid) -G $(sudoers_gid) -M $(sudoers_mode) \ $(srcdir)/sudoers $(DESTDIR)$(sudoersdir)/sudoers -install-man: +install-man: install-dirs $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudo.$(mantype) $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) @rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) ln $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) diff --git a/README b/README index 301ca55..bf7522f 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Sudo version 1.7.0 +This is Sudo version 1.7.2 The sudo philosophy =================== diff --git a/TROUBLESHOOTING b/TROUBLESHOOTING index a90b5eb..8ca2080 100644 --- a/TROUBLESHOOTING +++ b/TROUBLESHOOTING @@ -177,6 +177,14 @@ A) The default user sudo tries to run things as is always root, even if Defaults:bob runas_default=oracle would achieve the desired result ofr the preceding sudoers fragment. +Q) When I try to run sudo via ssh, I get the error: + sudo: no tty present and no askpass program specified +A) ssh does not allocate a tty by default when running a remote command. + Without a tty, sudo cannot disable echo when prompting for a password. + You can use ssh's "-t" option to force it to allocate a tty. + Alternately, if you do not mind your password being echoed to the + screen, you can use the "visiblepw" sudoers option to allow this. + 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/WHATSNEW b/WHATSNEW index 2d36f06..657fd29 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -1,3 +1,73 @@ +What's new in Sudo 1.7.2? + + * A new #includedir directive is available in sudoers. This can be + used to implement an /etc/sudo.d directory. Files in an includedir + are not edited by visudo unless they contain a syntax error. + + * The -g option did not work properly when only setting the group + (and not the user). Also, in -l mode the wrong user was displayed + for sudoers entries where only the group was allowed to be set. + + * Fixed a problem with the alias checking in visudo which + could prevent visudo from exiting. + + * Sudo will now correctly parse the shell-style /etc/environment + file format used by pam_env on Linux. + + * When doing password and group database lookups, sudo will only + cache an entry by name or by id, depending on how the entry was + looked up. Previously, sudo would cache by both name and id + from a single lookup, but this breaks sites that have multiple + password or group database names that map to the same uid or + gid. + + * User and group names in sudoers may now be enclosed in double + quotes to avoid having to escape special characters. + + * BSM audit fixes when changing to a non-root uid. + + * Experimental non-Unix group support. Currently only works with + Quest Authorization Services and allows Active Directory groups + fixes for Minix-3. + + * For Netscape/Mozilla-derived LDAP SDKs the certificate and key + paths may be specified as a directory or a file. However, version + 5.0 of the SDK only appears to support using a directory (despite + documentation to the contrary). If SSL client initialization + fails and the certificate or key paths look like they could be + default file name, strip off the last path element and try again. + + * A setenv() compatibility fix for Linux systems, where a NULL + value is treated the same as an empty string and the variable + name is checked against the NULL pointer. + +What's new in Sudo 1.7.1? + + * A new Defaults option "pwfeedback" will cause sudo to provide visual + feedback when the user is entering a password. + + * A new Defaults option "fast_glob" will cause sudo to use the fnmatch() + function for file name globbing instead of glob(). When this option + is enabled, sudo will not check the file system when expanding wildcards. + This is faster but a side effect is that relative paths with wildcard + will no longer work. + + * New BSM audit support for systems that support it such as FreeBSD + and Mac OS X. + + * The file name specified with the #include directive may now include + a %h escape which is expanded to the short form of hostname. + + * The -k flag may now be specified along with a command, causing the + user's timestamp file to be ignored. + + * New support for Tivoli-based LDAP START_TLS, present in AIX. + + * New support for /etc/netsvc.conf on AIX. + + * The unused alias checks in visudo now handle the case of an alias + referring to another alias. + What's new in Sudo 1.7.0? * Rewritten parser that converts sudoers into a set of data structures. @@ -77,3 +147,7 @@ What's new in Sudo 1.7.0? * visudo will now check the sudoers file owner and mode in -c (check) mode when the -s (strict) flag is specified. + + * A new Defaults option "umask_override" will cause sudo to set the + umask specified in sudoers even if it is more permissive than the + invoking user's umask. diff --git a/aclocal.m4 b/aclocal.m4 index 13089f0..1a6d990 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,7 @@ dnl Local m4 macros for autoconf (used by sudo) dnl -dnl Copyright (c) 1994-1996,1998-2004 Todd C. Miller +dnl Copyright (c) 1994-1996, 1998-2005, 2007-2009 +dnl Todd C. Miller dnl dnl XXX - should cache values in all cases!!! dnl @@ -219,7 +220,7 @@ dnl dnl check for isblank(3) dnl AC_DEFUN([SUDO_FUNC_ISBLANK], - [AC_CACHE_CHECK([for isblank], sudo_cv_func_isblank, + [AC_CACHE_CHECK([for isblank], [sudo_cv_func_isblank], [AC_TRY_LINK([#include ], [return (isblank('a'));], sudo_cv_func_isblank=yes, sudo_cv_func_isblank=no)]) ] [ @@ -230,6 +231,43 @@ AC_DEFUN([SUDO_FUNC_ISBLANK], fi ]) +dnl +dnl check unsetenv() return value +dnl +AC_DEFUN([SUDO_FUNC_UNSETENV_VOID], + [AC_CACHE_CHECK([whether unsetenv returns void], [sudo_cv_func_unsetenv_void], + [AC_RUN_IFELSE([AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT + int unsetenv(); + ], [ + [return unsetenv("FOO") != 0;] + ]) + ], + [sudo_cv_func_unsetenv_void=no], + [sudo_cv_func_unsetenv_void=yes], + [sudo_cv_func_unsetenv_void=yes])]) + if test $sudo_cv_func_unsetenv_void = yes; then + AC_DEFINE(UNSETENV_VOID, 1, + [Define to 1 if the `unsetenv' function returns void instead of `int'.]) + fi + ]) + +dnl +dnl check putenv() argument for const +dnl +AC_DEFUN([SUDO_FUNC_PUTENV_CONST], +[AC_CACHE_CHECK([whether putenv has a const argument], +sudo_cv_func_putenv_const, +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT +int putenv(const char *string) {return 0;}], [])], + [sudo_cv_func_putenv_const=yes], + [sudo_cv_func_putenv_const=no]) + ]) + if test $sudo_cv_func_putenv_const = yes; then + AC_DEFINE(PUTENV_CONST, 1, [Define to 1 if the `putenv' has a const argument.]) + fi +]) + dnl dnl check for sa_len field in struct sockaddr dnl diff --git a/alias.c b/alias.c index 9a03069..e8fec56 100644 --- a/alias.c +++ b/alias.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005m, 2007-2008 + * Copyright (c) 2004-2005m, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -47,7 +47,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: alias.c,v 1.14 2008/11/18 13:29:58 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: alias.c,v 1.18 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ /* @@ -56,17 +56,11 @@ __unused static const char rcsid[] = "$Sudo: alias.c,v 1.14 2008/11/18 13:29:58 struct rbtree *aliases; unsigned int alias_seqno; -/* - * Local protoypes - */ -static int alias_compare __P((const void *, const void *)); -static void alias_free __P((void *)); - /* * Comparison function for the red-black tree. * Aliases are sorted by name with the type used as a tie-breaker. */ -static int +int alias_compare(v1, v2) const void *v1, *v2; { @@ -88,7 +82,7 @@ alias_compare(v1, v2) * Returns a pointer to the alias structure or NULL if not found. */ struct alias * -find_alias(name, type) +alias_find(name, type) char *name; int type; { @@ -161,7 +155,7 @@ no_aliases() /* * Free memory used by an alias struct and its members. */ -static void +void alias_free(v) void *v; { @@ -185,9 +179,9 @@ alias_free(v) } /* - * Find the named alias, delete it from the tree and recover its resources. + * Find the named alias, remove it from the tree and return it. */ -int +struct alias * alias_remove(name, type) char *name; int type; @@ -198,10 +192,9 @@ alias_remove(name, type) key.name = name; key.type = type; if ((node = rbfind(aliases, &key)) == NULL) - return(FALSE); + return(NULL); a = rbdelete(aliases, node); - alias_free(a); - return(TRUE); + return(a); } void diff --git a/audit.c b/audit.c new file mode 100644 index 0000000..59ea526 --- /dev/null +++ b/audit.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef __STDC__ +# include +#else +# include +#endif + +#include "compat.h" +#include "logging.h" + +#ifdef HAVE_BSM_AUDIT +# include "bsm_audit.h" +#endif + +void +#ifdef __STDC__ +audit_success(char **exec_args) +#else +audit_success(exec_args) + const char **exec_args; +#endif +{ +#ifdef HAVE_BSM_AUDIT + bsm_audit_success(exec_args); +#endif +} + +void +#ifdef __STDC__ +audit_failure(char **exec_args, char const *const fmt, ...) +#else +audit_failure(exec_args, fmt, va_alist) + const char **exec_args; + char const *const fmt; + va_dcl +#endif +{ + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif +#ifdef HAVE_BSM_AUDIT + bsm_audit_failure(exec_args, fmt, ap); +#endif + va_end(ap); +} diff --git a/auth/aix_auth.c b/auth/aix_auth.c index 14343ef..853ceb8 100644 --- a/auth/aix_auth.c +++ b/auth/aix_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2008 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -47,7 +47,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: aix_auth.c,v 1.25 2008/11/09 14:13:13 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: aix_auth.c,v 1.27 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ /* @@ -82,7 +82,7 @@ aixauth_cleanup(pw, auth) sudo_auth *auth; { /* Unset AUTHSTATE as it may not be correct for the runas user. */ - sudo_unsetenv("AUTHSTATE"); + unsetenv("AUTHSTATE"); return(AUTH_SUCCESS); } diff --git a/auth/pam.c b/auth/pam.c index cefb6d5..47820ba 100644 --- a/auth/pam.c +++ b/auth/pam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2008 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -73,12 +73,12 @@ #endif #ifndef lint -__unused static const char rcsid[] = "$Sudo: pam.c,v 1.66 2008/12/09 23:48:19 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: pam.c,v 1.68 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ static int sudo_conv __P((int, PAM_CONST struct pam_message **, struct pam_response **, void *)); -static char *def_prompt; +static char *def_prompt = "Password:"; static int gotintr; #ifndef PAM_DATA_SILENT diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c index 509f26f..fa1419f 100644 --- a/auth/sudo_auth.c +++ b/auth/sudo_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008 Todd C. Miller + * Copyright (c) 1999-2005, 2008-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -53,7 +53,7 @@ #include "insults.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo_auth.c,v 1.38 2008/11/07 17:45:52 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo_auth.c,v 1.40 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ sudo_auth auth_switch[] = { @@ -100,6 +100,9 @@ verify_user(pw, prompt) char *p; sudo_auth *auth; sigaction_t sa, osa; +#ifdef HAVE_BSM_AUDIT + extern char **NewArgv; +#endif /* Enable suspend during password entry. */ sigemptyset(&sa.sa_mask); @@ -108,11 +111,15 @@ verify_user(pw, prompt) (void) sigaction(SIGTSTP, &sa, &osa); /* Make sure we have at least one auth method. */ - if (auth_switch[0].name == NULL) + if (auth_switch[0].name == NULL) { +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "no authentication methods"); +#endif log_error(0, "%s %s %s", "There are no authentication methods compiled into sudo!", "If you want to turn off authentication, use the", "--disable-authentication configure option."); + } /* Set FLAG_ONEANDONLY if there is only one auth method. */ if (auth_switch[1].name == NULL) @@ -127,8 +134,12 @@ verify_user(pw, prompt) status = (auth->init)(pw, &prompt, auth); if (status == AUTH_FAILURE) CLR(auth->flags, FLAG_CONFIGURED); - else if (status == AUTH_FATAL) /* XXX log */ + else if (status == AUTH_FATAL) { /* XXX log */ +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "authentication failure"); +#endif exit(1); /* assume error msg already printed */ + } if (NEEDS_USER(auth)) set_perms(PERM_ROOT); @@ -145,8 +156,12 @@ verify_user(pw, prompt) status = (auth->setup)(pw, &prompt, auth); if (status == AUTH_FAILURE) CLR(auth->flags, FLAG_CONFIGURED); - else if (status == AUTH_FATAL) /* XXX log */ + else if (status == AUTH_FATAL) {/* XXX log */ +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "authentication failure"); +#endif exit(1); /* assume error msg already printed */ + } if (NEEDS_USER(auth)) set_perms(PERM_ROOT); @@ -193,8 +208,12 @@ cleanup: set_perms(PERM_USER); status = (auth->cleanup)(pw, auth); - if (status == AUTH_FATAL) /* XXX log */ + if (status == AUTH_FATAL) { /* XXX log */ +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "authentication failure"); +#endif exit(1); /* assume error msg already printed */ + } if (NEEDS_USER(auth)) set_perms(PERM_ROOT); @@ -212,12 +231,18 @@ cleanup: flags = 0; else flags = NO_MAIL; +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "authentication failure"); +#endif log_error(flags, "%d incorrect password attempt%s", def_passwd_tries - counter, (def_passwd_tries - counter == 1) ? "" : "s"); } /* FALLTHROUGH */ case AUTH_FATAL: +#ifdef HAVE_BSM_AUDIT + audit_failure(NewArgv, "authentication failure"); +#endif exit(1); } /* NOTREACHED */ diff --git a/auth/sudo_auth.h b/auth/sudo_auth.h index ed1545f..42ac49b 100644 --- a/auth/sudo_auth.h +++ b/auth/sudo_auth.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2008 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Sudo: sudo_auth.h,v 1.28 2008/12/02 17:30:39 millert Exp $ + * $Sudo: sudo_auth.h,v 1.29 2009/05/25 12:02:42 millert Exp $ */ #ifndef SUDO_AUTH_H diff --git a/bsm_audit.c b/bsm_audit.c new file mode 100644 index 0000000..054d621 --- /dev/null +++ b/bsm_audit.c @@ -0,0 +1,173 @@ +/* + * 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. + */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__)); + +static int +audit_sudo_selected(int sf) +{ + auditinfo_addr_t ainfo_addr; + struct au_mask *mask; + auditinfo_t ainfo; + int rc, sorf; + + if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) { + if (errno == ENOSYS) { + if (getaudit(&ainfo) < 0) + log_error(0, "getaudit: failed"); + mask = &ainfo.ai_mask; + } else + log_error(0, "getaudit: failed"); + } else + mask = &ainfo_addr.ai_mask; + sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE; + rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD); + return (rc); +} + +void +bsm_audit_success(char **exec_args) +{ + auditinfo_addr_t ainfo_addr; + auditinfo_t ainfo; + token_t *tok; + au_id_t auid; + long au_cond; + int aufd; + pid_t pid; + + pid = getpid(); + /* + * If we are not auditing, don't cut an audit record; just return. + */ + if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) { + if (errno == ENOSYS) + return; + log_error(0, "Could not determine audit condition"); + } + if (au_cond == AUC_NOAUDIT) + return; + /* + * Check to see if the preselection masks are interested in seeing + * this event. + */ + if (!audit_sudo_selected(0)) + return; + if (getauid(&auid) < 0) + log_error(0, "getauid failed"); + if ((aufd = au_open()) == -1) + log_error(0, "au_open: failed"); + if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { + tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), + getuid(), pid, pid, &ainfo_addr.ai_termid); + } else if (errno == ENOSYS) { + /* + * NB: We should probably watch out for ERANGE here. + */ + if (getaudit(&ainfo) < 0) + log_error(0, "getaudit: failed"); + tok = au_to_subject(auid, geteuid(), getegid(), getuid(), + getuid(), pid, pid, &ainfo.ai_termid); + } else + log_error(0, "getaudit: failed"); + if (tok == NULL) + log_error(0, "au_to_subject: failed"); + au_write(aufd, tok); + tok = au_to_exec_args(exec_args); + if (tok == NULL) + log_error(0, "au_to_exec_args: failed"); + au_write(aufd, tok); + tok = au_to_return32(0, 0); + if (tok == NULL) + log_error(0, "au_to_return32: failed"); + au_write(aufd, tok); + if (au_close(aufd, 1, AUE_sudo) == -1) + log_error(0, "unable to commit audit record"); +} + +void +bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap) +{ + auditinfo_addr_t ainfo_addr; + auditinfo_t ainfo; + char text[256]; + token_t *tok; + long au_cond; + au_id_t auid; + pid_t pid; + int aufd; + + pid = getpid(); + /* + * If we are not auditing, don't cut an audit record; just return. + */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno == ENOSYS) + return; + log_error(0, "Could not determine audit condition"); + } + if (au_cond == AUC_NOAUDIT) + return; + if (!audit_sudo_selected(1)) + return; + if (getauid(&auid) < 0) + log_error(0, "getauid: failed"); + if ((aufd = au_open()) == -1) + log_error(0, "au_open: failed"); + if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { + tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), + getuid(), pid, pid, &ainfo_addr.ai_termid); + } else if (errno == ENOSYS) { + if (getaudit(&ainfo) < 0) + log_error(0, "getaudit: failed"); + tok = au_to_subject(auid, geteuid(), getegid(), getuid(), + getuid(), pid, pid, &ainfo.ai_termid); + } else + log_error(0, "getaudit: failed"); + if (tok == NULL) + log_error(0, "au_to_subject: failed"); + au_write(aufd, tok); + tok = au_to_exec_args(exec_args); + if (tok == NULL) + log_error(0, "au_to_exec_args: failed"); + au_write(aufd, tok); + (void) vsnprintf(text, sizeof(text), fmt, ap); + tok = au_to_text(text); + if (tok == NULL) + log_error(0, "au_to_text: failed"); + au_write(aufd, tok); + tok = au_to_return32(EPERM, 1); + if (tok == NULL) + log_error(0, "au_to_return32: failed"); + au_write(aufd, tok); + if (au_close(aufd, 1, AUE_sudo) == -1) + log_error(0, "unable to commit audit record"); +} diff --git a/version.h b/bsm_audit.h similarity index 61% rename from version.h rename to bsm_audit.h index fa354e0..6ccb79d 100644 --- a/version.h +++ b/bsm_audit.h @@ -1,6 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2008 - * Todd C. Miller + * 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 @@ -13,17 +12,12 @@ * 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. - * - * $Sudo: version.h,v 1.71 2008/11/09 14:13:12 millert Exp $ */ -#ifndef _SUDO_VERSION_H -#define _SUDO_VERSION_H +#ifndef _SUDO_BSM_AUDIT_H +#define _SUDO_BSM_AUDIT_H -static const char version[] = "1.7.0"; +void bsm_audit_success(char **); +void bsm_audit_failure(char **, char const * const, va_list); -#endif /* _SUDO_VERSION_H */ +#endif /* _SUDO_BSM_AUDIT_H */ diff --git a/check.c b/check.c index fedc916..bdce34e 100644 --- a/check.c +++ b/check.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996,1998-2005, 2007-2008 + * Copyright (c) 1993-1996,1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -59,7 +59,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: check.c,v 1.245 2008/11/25 17:01:34 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: check.c,v 1.247 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ /* Status codes for timestamp_status() */ @@ -84,24 +84,29 @@ static void update_timestamp __P((char *, char *)); * verify who he/she is. */ void -check_user(validated, interactive) +check_user(validated, mode) int validated; - int interactive; + int mode; { char *timestampdir = NULL; char *timestampfile = NULL; char *prompt; int status; - if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt()) - return; + if (mode & MODE_INVALIDATE) { + /* do not check or update timestamp */ + status = TS_ERROR; + } else { + if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt()) + return; - build_timestamp(×tampdir, ×tampfile); - status = timestamp_status(timestampdir, timestampfile, user_name, + build_timestamp(×tampdir, ×tampfile); + status = timestamp_status(timestampdir, timestampfile, user_name, TS_MAKE_DIRS); + } if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) { /* Bail out if we are non-interactive and a password is required */ - if (!interactive) + if (ISSET(mode, MODE_NONINTERACTIVE)) errorx(1, "sorry, a password is required to run %s", getprogname()); /* If user specified -A, make sure we have an askpass helper. */ @@ -139,7 +144,6 @@ check_user(validated, interactive) /* * Standard sudo lecture. - * TODO: allow the user to specify a file name instead. */ static void lecture(status) diff --git a/config.h.in b/config.h.in index 70de108..18698f4 100644 --- a/config.h.in +++ b/config.h.in @@ -32,6 +32,9 @@ /* A colon-separated list of pathnames to be used as the editor for visudo. */ #undef EDITOR +/* Define to enable environment debugging. */ +#undef ENV_DEBUG + /* Define to 1 if you want visudo to honor the EDITOR and VISUAL env variables. */ #undef ENV_EDITOR @@ -70,6 +73,9 @@ /* Define to 1 if you use BSD authentication. */ #undef HAVE_BSD_AUTH_H +/* Define to 1 to enable BSM auditing. */ +#undef HAVE_BSM_AUDIT + /* Define to 1 if you have the `closefrom' function. */ #undef HAVE_CLOSEFROM @@ -92,6 +98,9 @@ /* Define to 1 if you have the `dispcrypt' function. */ #undef HAVE_DISPCRYPT +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + /* Define to 1 if your glob.h defines the GLOB_BRACE and GLOB_TILDE flags. */ #undef HAVE_EXTENDED_GLOB @@ -243,12 +252,18 @@ /* Define to 1 if you have the `ldap_search_ext_s' function. */ #undef HAVE_LDAP_SEARCH_EXT_S +/* Define to 1 if you have the `ldap_ssl_client_init' function. */ +#undef HAVE_LDAP_SSL_CLIENT_INIT + /* Define to 1 if you have the header file. */ #undef HAVE_LDAP_SSL_H /* Define to 1 if you have the `ldap_start_tls_s' function. */ #undef HAVE_LDAP_START_TLS_S +/* Define to 1 if you have the `ldap_start_tls_s_np' function. */ +#undef HAVE_LDAP_START_TLS_S_NP + /* Define to 1 if you have the `ldap_str2dn' function. */ #undef HAVE_LDAP_STR2DN @@ -333,6 +348,9 @@ /* Define to 1 to enable SELinux RBAC support. */ #undef HAVE_SELINUX +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID @@ -460,6 +478,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + /* Define to 1 if you have the `utimes' function. */ #undef HAVE_UTIMES @@ -493,6 +514,9 @@ /* The message given when a bad password is entered. */ #undef INCORRECT_PASSWORD +/* The name of libvas.so */ +#undef LIBVAS_SO + /* The syslog facility sudo will use. */ #undef LOGFAC @@ -534,6 +558,21 @@ /* Define to 1 if root should not be allowed to use sudo. */ #undef NO_ROOT_SUDO +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + /* The default password prompt. */ #undef PASSPROMPT @@ -550,6 +589,9 @@ /* The syslog priority sudo will use for successful attempts. */ #undef PRI_SUCCESS +/* Define to 1 if the `putenv' has a const argument. */ +#undef PUTENV_CONST + /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE @@ -601,6 +643,9 @@ /* The number of tries a user gets to enter their password. */ #undef TRIES_FOR_PASSWORD +/* Define to 1 if the `unsetenv' function returns void instead of `int'. */ +#undef UNSETENV_VOID + /* Define to 1 if you want to insult the user for entering an incorrect password. */ #undef USE_INSULTS @@ -611,6 +656,9 @@ /* Define to 1 if you want a different ticket file for each tty. */ #undef USE_TTY_TICKETS +/* Define to 1 if using a non-unix group lookup implementation. */ +#undef USING_NONUNIX_GROUPS + /* Define to avoid using the passwd/shadow file for authentication. */ #undef WITHOUT_PASSWD diff --git a/configure b/configure index 0bf4e23..1d45b21 100755 --- a/configure +++ b/configure @@ -1,6 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for sudo 1.7. +# Generated by GNU Autoconf 2.61 for sudo 1.7.2. +# +# Report bugs to . # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -722,9 +724,9 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.7' -PACKAGE_STRING='sudo 1.7' -PACKAGE_BUGREPORT='' +PACKAGE_VERSION='1.7.2' +PACKAGE_STRING='sudo 1.7.2' +PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/' # Factoring default headers for most tests. ac_includes_default="\ @@ -799,6 +801,7 @@ LIBS build_alias host_alias target_alias +HAVE_BSM_AUDIT LIBTOOL CFLAGS PROGS @@ -835,6 +838,7 @@ BSDAUTH_USAGE SELINUX_USAGE LDAP LOGINCAP_USAGE +NONUNIX_GROUPS_IMPL timedir timeout password_timeout @@ -864,6 +868,7 @@ path_info ldap_conf ldap_secret nsswitch_conf +netsvc_conf EGREPPROG CC ac_ct_CC @@ -878,10 +883,6 @@ host host_cpu host_vendor host_os -target -target_cpu -target_vendor -target_os SED GREP EGREP @@ -897,6 +898,7 @@ TRPROG NROFFPROG YACC YFLAGS +FLEX LIBOBJS KRB5CONFIG LTLIBOBJS' @@ -1414,7 +1416,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sudo 1.7 to adapt to many kinds of systems. +\`configure' configures sudo 1.7.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1474,13 +1476,12 @@ _ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.7:";; + short | recursive ) echo "Configuration of sudo 1.7.2:";; esac cat <<\_ACEOF @@ -1499,6 +1500,7 @@ Optional Features: --enable-shell-sets-home Set $HOME to target user in shell mode --disable-path-info Print 'command not allowed' not 'command not found' + --enable-env-debug Whether to enable environment debugging. --enable-gss-krb5-ccache-name Use GSS-API to set the Kerberos V cred cache name --enable-static[=PKGS] build static libraries [default=no] @@ -1517,6 +1519,7 @@ Optional Packages: --with-CC C compiler to use --with-rpath pass -R flag in addition to -L for lib paths --with-blibpath=PATH pass -blibpath flag to ld for additional lib paths + --with-bsm-audit enable BSM audit support --with-incpath additional places to look for include files --with-libpath additional places to look for libraries --with-libraries additional libraries to link with @@ -1527,10 +1530,10 @@ Optional Packages: --with-skey=DIR enable S/Key support --with-opie=DIR enable OPIE support --with-long-otp-prompt use a two line OTP (skey/opie) prompt - --with-SecurID[=DIR] enable SecurID support - --with-fwtk[=DIR] enable FWTK AuthSRV support - --with-kerb4[=DIR] enable Kerberos IV support - --with-kerb5[=DIR] enable Kerberos V support + --with-SecurID=DIR enable SecurID support + --with-fwtk=DIR enable FWTK AuthSRV support + --with-kerb4=DIR enable Kerberos IV support + --with-kerb5=DIR enable Kerberos V support --with-aixauth enable AIX general authentication support --with-pam enable PAM support --with-AFS enable AFS support @@ -1546,7 +1549,8 @@ Optional Packages: --with-logpath path to the sudo log file --with-loglen maximum length of a log file line (default is 80) --with-ignore-dot ignore '.' in the PATH - --without-mail-if-no-user do not send mail if user not in sudoers + --without-mail-if-no-user + do not send mail if user not in sudoers --with-mail-if-no-host send mail if user in sudoers but not for this host --with-mail-if-noperms send mail if user not allowed to run command --with-mailto who should get sudo mail (default is "root") @@ -1555,20 +1559,23 @@ Optional Packages: --with-badpass-message message the user sees when the password is wrong --with-fqdn expect fully qualified hosts in sudoers --with-timedir path to the sudo timestamp dir - --with-sendmail=path set path to sendmail + --with-sendmail set path to sendmail --without-sendmail do not send mail at all --with-sudoers-mode mode of sudoers file (defaults to 0440) --with-sudoers-uid uid that owns sudoers file (defaults to 0) --with-sudoers-gid gid that owns sudoers file (defaults to 0) - --with-umask umask with which the prog should run (default is 022) + --with-umask umask with which the prog should run (default is + 022) --without-umask Preserves the umask of the user invoking sudo. --with-runas-default User to run commands as (default is "root") --with-exempt=group no passwd needed for users in this group --with-editor=path Default editor for visudo (defaults to vi) --with-env-editor Use the environment variable EDITOR for visudo --with-passwd-tries number of tries to enter password (default is 3) - --with-timeout minutes before sudo asks for passwd again (def is 5 minutes) - --with-password-timeout passwd prompt timeout in minutes (default is 5 minutes) + --with-timeout minutes before sudo asks for passwd again (def is 5 + minutes) + --with-password-timeout passwd prompt timeout in minutes (default is 5 + minutes) --with-tty-tickets use a different ticket file for each tty --with-insults insult the user for entering an incorrect password --with-all-insults include all the sudo insult sets @@ -1576,20 +1583,26 @@ Optional Packages: --with-csops-insults include CSOps insults --with-hal-insults include 2001-like insults --with-goons-insults include the insults from the "Goon Show" - --with-nsswitch[=PATH] path to nsswitch.conf - --with-ldap[=DIR] enable LDAP support + --with-nsswitch=PATH path to nsswitch.conf + --with-ldap=DIR enable LDAP support --with-ldap-conf-file path to LDAP configuration file --with-ldap-secret-file path to LDAP secret password file - --with-pc-insults replace politically incorrect insults with less offensive ones + --with-pc-insults replace politically incorrect insults with less + offensive ones --with-secure-path override the user's path with a built-in one --without-interfaces don't try to read the ip addr of ether interfaces --with-stow properly handle GNU stow packaging --with-askpass=PATH Fully qualified pathname of askpass helper + --with-libvas=NAME Name of the libvas shared library + (default=libvas.so) + --with-libvas-rpath=PATH + Path to look for libvas in [default=/opt/quest/lib] --with-selinux enable SELinux support --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-noexec=PATH fully qualified pathname of sudo_noexec.so + --with-netsvc=PATH path to netsvc.conf Some influential environment variables: CC C compiler command @@ -1609,6 +1622,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. +Report bugs to . _ACEOF ac_status=$? fi @@ -1669,7 +1683,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.7 +sudo configure 1.7.2 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1683,7 +1697,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sudo $as_me 1.7, which was +It was created by sudo $as_me 1.7.2, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -2038,8 +2052,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h pathnames.h" -{ echo "$as_me:$LINENO: Configuring Sudo version 1.7" >&5 -echo "$as_me: Configuring Sudo version 1.7" >&6;} +{ echo "$as_me:$LINENO: Configuring Sudo version $PACKAGE_VERSION" >&5 +echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} + + + @@ -2235,6 +2252,26 @@ fi +# Check whether --with-bsm-audit was given. +if test "${with_bsm_audit+set}" = set; then + withval=$with_bsm_audit; case $with_bsm_audit in + yes) cat >>confdefs.h <<\_ACEOF +#define HAVE_BSM_AUDIT 1 +_ACEOF + + SUDO_LIBS="${SUDO_LIBS} -lbsm" + SUDO_OBJS="${SUDO_OBJS} bsm_audit.o" + ;; + no) ;; + *) { { echo "$as_me:$LINENO: error: \"--with-bsm-audit does not take an argument.\"" >&5 +echo "$as_me: error: \"--with-bsm-audit does not take an argument.\"" >&2;} + { (exit 1); exit 1; }; } + ;; +esac +fi + + + # Check whether --with-incpath was given. if test "${with_incpath+set}" = set; then withval=$with_incpath; case $with_incpath in @@ -3579,21 +3616,12 @@ if test "${with_nsswitch+set}" = set; then esac fi -if test ${with_nsswitch-"yes"} != "no"; then - cat >>confdefs.h <>confdefs.h <<\_ACEOF #define HAVE_LDAP 1 _ACEOF @@ -3770,6 +3798,44 @@ fi +# Check whether --with-libvas was given. +if test "${with_libvas+set}" = set; then + withval=$with_libvas; case $with_libvas in + yes) with_libvas=libvas.so + ;; + no) ;; + *) +cat >>confdefs.h <<_ACEOF +#define LIBVAS_SO "$with_with_libvas" +_ACEOF + + ;; +esac +if test X"$with_libvas" != X"no"; then + +cat >>confdefs.h <<_ACEOF +#define LIBVAS_SO "$with_libvas" +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define USING_NONUNIX_GROUPS 1 +_ACEOF + + NONUNIX_GROUPS_IMPL="vasgroups.o" + +# Check whether --with-libvas-rpath was given. +if test "${with_libvas_rpath+set}" = set; then + withval=$with_libvas_rpath; LIBVAS_RPATH=$withval +else + LIBVAS_RPATH=/opt/quest/lib +fi + +fi + +fi + + + { echo "$as_me:$LINENO: checking whether to do user authentication by default" >&5 echo $ECHO_N "checking whether to do user authentication by default... $ECHO_C" >&6; } # Check whether --enable-authentication was given. @@ -4014,6 +4080,34 @@ echo "${ECHO_T}no" >&6; } fi +{ echo "$as_me:$LINENO: checking whether to enable environment debugging" >&5 +echo $ECHO_N "checking whether to enable environment debugging... $ECHO_C" >&6; } +# Check whether --enable-env_debug was given. +if test "${enable_env_debug+set}" = set; then + enableval=$enable_env_debug; case "$enableval" in + yes) { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + cat >>confdefs.h <<\_ACEOF +#define ENV_DEBUG 1 +_ACEOF + + ;; + no) { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; + *) { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { echo "$as_me:$LINENO: WARNING: Ignoring unknown argument to --enable-env-debug: $enableval" >&5 +echo "$as_me: WARNING: Ignoring unknown argument to --enable-env-debug: $enableval" >&2;} + ;; + esac + +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + # Check whether --with-selinux was given. if test "${with_selinux+set}" = set; then @@ -5441,49 +5535,6 @@ IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -{ echo "$as_me:$LINENO: checking target system type" >&5 -echo $ECHO_N "checking target system type... $ECHO_C" >&6; } -if test "${ac_cv_target+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "x$target_alias" = x; then - ac_cv_target=$ac_cv_host -else - ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} - { (exit 1); exit 1; }; } -fi - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 -echo "${ECHO_T}$ac_cv_target" >&6; } -case $ac_cv_target in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 -echo "$as_me: error: invalid value of canonical target" >&2;} - { (exit 1); exit 1; }; };; -esac -target=$ac_cv_target -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_target -shift -target_cpu=$1 -target_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -target_os=$* -IFS=$ac_save_IFS -case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- # Check whether --enable-static was given. if test "${enable_static+set}" = set; then enableval=$enable_static; p=${PACKAGE-default} @@ -5509,6 +5560,8 @@ fi + + # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} @@ -6209,7 +6262,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6212 "configure"' > conftest.$ac_ext + echo '#line 6265 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6759,7 +6812,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -7971,7 +8029,7 @@ echo "${ECHO_T}$lt_cv_ld_exported_symbols_list" >&6; } esac -enable_dlopen=no +enable_dlopen=yes enable_win32_dll=no # Check whether --enable-libtool-lock was given. @@ -8068,11 +8126,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8071: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8129: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8075: \$? = $ac_status" >&5 + echo "$as_me:8133: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8358,11 +8416,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8361: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8419: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8365: \$? = $ac_status" >&5 + echo "$as_me:8423: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8462,11 +8520,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8465: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8523: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8469: \$? = $ac_status" >&5 + echo "$as_me:8527: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10822,7 +10880,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5 +echo $ECHO_N "checking whether $CC understands +DAportable... $ECHO_C" >&6; } +if test "${sudo_cv_var_daportable+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + sudo_cv_var_daportable=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + sudo_cv_var_daportable=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $sudo_cv_var_daportable" >&5 +echo "${ECHO_T}$sudo_cv_var_daportable" >&6; } + if test X"$sudo_cv_var_daportable" != X"yes"; then + CFLAGS="$_CFLAGS" + fi + case "$host" in *-*-hpux1-8.*) cat >>confdefs.h <<\_ACEOF @@ -12933,6 +13067,47 @@ fi done test -n "$YACC" || YACC="yacc" +# Extract the first word of "flex", so it can be a program name with args. +set dummy flex; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FLEX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FLEX in + [\\/]* | ?:[\\/]*) + ac_cv_path_FLEX="$FLEX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FLEX="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FLEX" && ac_cv_path_FLEX="flex" + ;; +esac +fi +FLEX=$ac_cv_path_FLEX +if test -n "$FLEX"; then + { echo "$as_me:$LINENO: result: $FLEX" >&5 +echo "${ECHO_T}$FLEX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + { echo "$as_me:$LINENO: checking for mv" >&5 echo $ECHO_N "checking for mv... $ECHO_C" >&6; } if test -f "/usr/bin/mv"; then @@ -13724,7 +13899,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -13927,7 +14107,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -14070,7 +14255,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -14212,7 +14402,12 @@ echo "$as_me: WARNING: project.h: section \"Present But Cannot Be Compiled\" echo "$as_me: WARNING: project.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: project.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: project.h: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for project.h" >&5 @@ -15629,9 +15824,10 @@ LIBS=$ac_save_LIBS + for ac_func in strchr strrchr memchr memcpy memset sysconf tzset \ strftime setrlimit initgroups getgroups fstat gettimeofday \ - setlocale getaddrinfo setsid + setlocale getaddrinfo setsid setenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -15724,9 +15920,8 @@ _ACEOF fi done -if test -z "$SKIP_SETRESUID"; then -for ac_func in setresuid +for ac_func in unsetenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -15815,20 +16010,13 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF - SKIP_SETREUID=yes -fi -done - -fi -if test -z "$SKIP_SETREUID"; then - -for ac_func in setreuid -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking whether unsetenv returns void" >&5 +echo $ECHO_N "checking whether unsetenv returns void... $ECHO_C" >&6; } +if test "${sudo_cv_func_unsetenv_void+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + sudo_cv_func_unsetenv_void=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -15836,72 +16024,304 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif +$ac_includes_default + int unsetenv(); int main () { -return $ac_func (); + + return unsetenv("FOO") != 0; + ; return 0; } + _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext +rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 + (eval "$ac_link") 2>&5 ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + sudo_cv_func_unsetenv_void=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +sudo_cv_func_unsetenv_void=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $sudo_cv_func_unsetenv_void" >&5 +echo "${ECHO_T}$sudo_cv_func_unsetenv_void" >&6; } + if test $sudo_cv_func_unsetenv_void = yes; then + +cat >>confdefs.h <<\_ACEOF +#define UNSETENV_VOID 1 +_ACEOF + + fi + +fi +done + +{ echo "$as_me:$LINENO: checking whether putenv has a const argument" >&5 +echo $ECHO_N "checking whether putenv has a const argument... $ECHO_C" >&6; } +if test "${sudo_cv_func_putenv_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int putenv(const char *string) {return 0;} +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + sudo_cv_func_putenv_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + sudo_cv_func_putenv_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $sudo_cv_func_putenv_const" >&5 +echo "${ECHO_T}$sudo_cv_func_putenv_const" >&6; } + if test $sudo_cv_func_putenv_const = yes; then + +cat >>confdefs.h <<\_ACEOF +#define PUTENV_CONST 1 +_ACEOF + + fi + +if test -z "$SKIP_SETRESUID"; then + +for ac_func in setresuid +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + SKIP_SETREUID=yes +fi +done + +fi +if test -z "$SKIP_SETREUID"; then + +for ac_func in setreuid +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` @@ -19386,6 +19806,22 @@ fi done +netsvc_conf='/etc/netsvc.conf' +nsswitch_conf='/etc/nsswitch.conf' +if test ${with_netsvc-"no"} != "no"; then + cat >>confdefs.h <>confdefs.h <&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -19887,7 +20328,12 @@ echo "$as_me: WARNING: bsd_auth.h: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: bsd_auth.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: bsd_auth.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: bsd_auth.h: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for bsd_auth.h" >&5 @@ -20337,7 +20783,12 @@ echo "$as_me: WARNING: krb.h: section \"Present But Cannot Be Compiled\"" >& echo "$as_me: WARNING: krb.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: krb.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: krb.h: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for krb.h" >&5 @@ -22483,128 +22934,29 @@ fi echo "${ECHO_T}$ac_cv_search_ber_set_option" >&6; } ac_res=$ac_cv_search_ber_set_option if test "$ac_res" != no; then - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - found=yes -else - found=no -fi - - if test X"$found" = X"yes" -a X"$LIBS" != X"$OLIBS"; then - LDAP_LIBS="$LDAP_LIBS -llber" - fi - { echo "$as_me:$LINENO: checking whether lber.h is needed" >&5 -echo $ECHO_N "checking whether lber.h is needed... $ECHO_C" >&6; } - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #include -int -main () -{ -(void)ldap_init(0, 0) - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - cat >>confdefs.h <<\_ACEOF -#define HAVE_LBER_H 1 -_ACEOF - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext - - - - - - - - - - - -for ac_func in ldap_initialize ldap_start_tls_s ldap_sasl_interactive_bind_s ldapssl_init ldapssl_set_strength ldap_search_ext_s ldap_unbind_ext_s ldap_str2dn ldap_create ldap_sasl_bind_s -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + found=yes +else + found=no +fi + if test X"$found" = X"yes" -a X"$LIBS" != X"$OLIBS"; then + LDAP_LIBS="$LDAP_LIBS -llber" + fi + { echo "$as_me:$LINENO: checking whether lber.h is needed" >&5 +echo $ECHO_N "checking whether lber.h is needed... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include int main () { -return $ac_func (); +(void)ldap_init(0, 0) ; return 0; } @@ -22627,30 +22979,27 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - eval "$as_ac_var=no" + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + cat >>confdefs.h <<\_ACEOF +#define HAVE_LBER_H 1 +_ACEOF + fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF -fi -done -for ac_header in sasl/sasl.h +for ac_header in sasl/sasl.h sasl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then @@ -22765,7 +23114,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -22785,6 +23139,101 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF +for ac_func in ldap_sasl_interactive_bind_s +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +else + break fi done @@ -22849,6 +23298,110 @@ fi done + + + + + + + + + + +for ac_func in ldap_initialize ldap_start_tls_s ldapssl_init ldapssl_set_strength ldap_search_ext_s ldap_unbind_ext_s ldap_str2dn ldap_create ldap_sasl_bind_s ldap_ssl_client_init ldap_start_tls_s_np +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + if test X"$check_gss_krb5_ccache_name" = X"yes"; then { echo "$as_me:$LINENO: checking for gss_krb5_ccache_name in -lgssapi" >&5 echo $ECHO_N "checking for gss_krb5_ccache_name in -lgssapi... $ECHO_C" >&6; } @@ -23169,7 +23722,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -23310,7 +23868,12 @@ echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - + ( cat <<\_ASBOX +## --------------------------------------- ## +## Report this to http://www.sudo.ws/bugs/ ## +## --------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -23347,6 +23910,14 @@ echo "$as_me: WARNING: Unable to locate gssapi.h, you will have to edit the Make LDFLAGS="$_LDFLAGS" fi +if test X"$LIBVAS_RPATH" != X""; then + if test -n "$blibpath"; then + blibpath_add="${blibpath_add}:$LIBVAS_RPATH" + else + LDFLAGS="$LDFLAGS -R$LIBVAS_RPATH" + fi +fi + if test -n "$blibpath"; then if test -n "$blibpath_add"; then SUDO_LDFLAGS="$SUDO_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}" @@ -23891,7 +24462,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sudo $as_me 1.7, which was +This file was extended by sudo $as_me 1.7.2, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23940,7 +24511,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -sudo config.status 1.7 +sudo config.status 1.7.2 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -24153,6 +24724,7 @@ LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim +HAVE_BSM_AUDIT!$HAVE_BSM_AUDIT$ac_delim LIBTOOL!$LIBTOOL$ac_delim CFLAGS!$CFLAGS$ac_delim PROGS!$PROGS$ac_delim @@ -24189,6 +24761,7 @@ BSDAUTH_USAGE!$BSDAUTH_USAGE$ac_delim SELINUX_USAGE!$SELINUX_USAGE$ac_delim LDAP!$LDAP$ac_delim LOGINCAP_USAGE!$LOGINCAP_USAGE$ac_delim +NONUNIX_GROUPS_IMPL!$NONUNIX_GROUPS_IMPL$ac_delim timedir!$timedir$ac_delim timeout!$timeout$ac_delim password_timeout!$password_timeout$ac_delim @@ -24211,8 +24784,6 @@ fqdn!$fqdn$ac_delim runas_default!$runas_default$ac_delim env_editor!$env_editor$ac_delim passwd_tries!$passwd_tries$ac_delim -tty_tickets!$tty_tickets$ac_delim -insults!$insults$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -24254,11 +24825,14 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +tty_tickets!$tty_tickets$ac_delim +insults!$insults$ac_delim root_sudo!$root_sudo$ac_delim path_info!$path_info$ac_delim ldap_conf!$ldap_conf$ac_delim ldap_secret!$ldap_secret$ac_delim nsswitch_conf!$nsswitch_conf$ac_delim +netsvc_conf!$netsvc_conf$ac_delim EGREPPROG!$EGREPPROG$ac_delim CC!$CC$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim @@ -24273,10 +24847,6 @@ host!$host$ac_delim host_cpu!$host_cpu$ac_delim host_vendor!$host_vendor$ac_delim host_os!$host_os$ac_delim -target!$target$ac_delim -target_cpu!$target_cpu$ac_delim -target_vendor!$target_vendor$ac_delim -target_os!$target_os$ac_delim SED!$SED$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim @@ -24292,6 +24862,7 @@ TRPROG!$TRPROG$ac_delim NROFFPROG!$NROFFPROG$ac_delim YACC!$YACC$ac_delim YFLAGS!$YFLAGS$ac_delim +FLEX!$FLEX$ac_delim LIBOBJS!$LIBOBJS$ac_delim KRB5CONFIG!$KRB5CONFIG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim @@ -24916,6 +25487,10 @@ fi + + + + diff --git a/configure.in b/configure.in index 6b09b5f..e21ad6f 100644 --- a/configure.in +++ b/configure.in @@ -1,18 +1,19 @@ dnl dnl Process this file with GNU autoconf to produce a configure script. -dnl $Sudo: configure.in,v 1.538 2008/12/09 21:13:01 millert Exp $ +dnl $Sudo: configure.in,v 1.549 2009/06/13 20:52:50 millert Exp $ dnl -dnl Copyright (c) 1994-1996,1998-2008 Todd C. Miller +dnl Copyright (c) 1994-1996,1998-2009 Todd C. Miller dnl -AC_INIT([sudo], [1.7]) +AC_INIT([sudo], [1.7.2], [http://www.sudo.ws/bugs/], [sudo]) AC_CONFIG_HEADER(config.h pathnames.h) dnl dnl This won't work before AC_INIT dnl -AC_MSG_NOTICE([Configuring Sudo version 1.7]) +AC_MSG_NOTICE([Configuring Sudo version $PACKAGE_VERSION]) dnl dnl Variables that get substituted in the Makefile and man pages dnl +AC_SUBST(HAVE_BSM_AUDIT) AC_SUBST(LIBTOOL) AC_SUBST(CFLAGS) AC_SUBST(PROGS) @@ -50,6 +51,7 @@ AC_SUBST(BSDAUTH_USAGE) AC_SUBST(SELINUX_USAGE) AC_SUBST(LDAP) AC_SUBST(LOGINCAP_USAGE) +AC_SUBST(NONUNIX_GROUPS_IMPL) dnl dnl Variables that get substituted in docs (not overridden by environment) dnl @@ -82,6 +84,7 @@ AC_SUBST(path_info) AC_SUBST(ldap_conf) AC_SUBST(ldap_secret) AC_SUBST(nsswitch_conf) +AC_SUBST(netsvc_conf) dnl dnl Initial values for above dnl @@ -159,14 +162,14 @@ dnl dnl Deprecated --with options (these all warn or generate an error) dnl -AC_ARG_WITH(otp-only, [ --with-otp-only deprecated], +AC_ARG_WITH(otp-only, [AS_HELP_STRING([--with-otp-only], [deprecated])], [case $with_otp_only in yes) with_passwd="no" AC_MSG_NOTICE([--with-otp-only option deprecated, treating as --without-passwd]) ;; esac]) -AC_ARG_WITH(alertmail, [ --with-alertmail deprecated], +AC_ARG_WITH(alertmail, [AS_HELP_STRING([--with-alertmail], [deprecated])], [case $with_alertmail in *) with_mailto="$with_alertmail" AC_MSG_NOTICE([--with-alertmail option deprecated, treating as --mailto]) @@ -177,7 +180,7 @@ dnl dnl Options for --with dnl -AC_ARG_WITH(CC, [ --with-CC C compiler to use], +AC_ARG_WITH(CC, [AS_HELP_STRING([--with-CC], [C compiler to use])], [case $with_CC in yes) AC_MSG_ERROR(["must give --with-CC an argument."]) ;; @@ -187,21 +190,35 @@ AC_ARG_WITH(CC, [ --with-CC C compiler to use], ;; esac]) -AC_ARG_WITH(rpath, [ --with-rpath pass -R flag in addition to -L for lib paths], +AC_ARG_WITH(rpath, [AS_HELP_STRING([--with-rpath], [pass -R flag in addition to -L for lib paths])], [case $with_rpath in yes|no) ;; *) AC_MSG_ERROR(["--with-rpath does not take an argument."]) ;; esac]) -AC_ARG_WITH(blibpath, [ --with-blibpath[=PATH] pass -blibpath flag to ld for additional lib paths], +AC_ARG_WITH(blibpath, [AS_HELP_STRING([--with-blibpath[=PATH]], [pass -blibpath flag to ld for additional lib paths])], [case $with_blibpath in yes|no) ;; *) AC_MSG_NOTICE([will pass -blibpath:${with_blibpath} to the loader.]) ;; esac]) -AC_ARG_WITH(incpath, [ --with-incpath additional places to look for include files], +dnl +dnl Handle BSM auditing support. +dnl +AC_ARG_WITH(bsm-audit, [AS_HELP_STRING([--with-bsm-audit], [enable BSM audit support])], +[case $with_bsm_audit in + yes) AC_DEFINE(HAVE_BSM_AUDIT) + SUDO_LIBS="${SUDO_LIBS} -lbsm" + SUDO_OBJS="${SUDO_OBJS} bsm_audit.o" + ;; + no) ;; + *) AC_MSG_ERROR(["--with-bsm-audit does not take an argument."]) + ;; +esac]) + +AC_ARG_WITH(incpath, [AS_HELP_STRING([--with-incpath], [additional places to look for include files])], [case $with_incpath in yes) AC_MSG_ERROR(["must give --with-incpath an argument."]) ;; @@ -214,7 +231,7 @@ AC_ARG_WITH(incpath, [ --with-incpath additional places to look for in ;; esac]) -AC_ARG_WITH(libpath, [ --with-libpath additional places to look for libraries], +AC_ARG_WITH(libpath, [AS_HELP_STRING([--with-libpath], [additional places to look for libraries])], [case $with_libpath in yes) AC_MSG_ERROR(["must give --with-libpath an argument."]) ;; @@ -224,7 +241,7 @@ AC_ARG_WITH(libpath, [ --with-libpath additional places to look for li ;; esac]) -AC_ARG_WITH(libraries, [ --with-libraries additional libraries to link with], +AC_ARG_WITH(libraries, [AS_HELP_STRING([--with-libraries], [additional libraries to link with])], [case $with_libraries in yes) AC_MSG_ERROR(["must give --with-libraries an argument."]) ;; @@ -234,7 +251,7 @@ AC_ARG_WITH(libraries, [ --with-libraries additional libraries to link w ;; esac]) -AC_ARG_WITH(devel, [ --with-devel add development options], +AC_ARG_WITH(devel, [AS_HELP_STRING([--with-devel], [add development options])], [case $with_devel in yes) AC_MSG_NOTICE([Setting up for development: -Wall, flex, yacc]) PROGS="${PROGS} testsudoers" @@ -247,7 +264,7 @@ AC_ARG_WITH(devel, [ --with-devel add development options], ;; esac]) -AC_ARG_WITH(efence, [ --with-efence link with -lefence for malloc() debugging], +AC_ARG_WITH(efence, [AS_HELP_STRING([--with-efence], [link with -lefence for malloc() debugging])], [case $with_efence in yes) AC_MSG_NOTICE([Sudo will link with -lefence (Electric Fence)]) LIBS="${LIBS} -lefence" @@ -260,7 +277,7 @@ AC_ARG_WITH(efence, [ --with-efence link with -lefence for malloc() d ;; esac]) -AC_ARG_WITH(csops, [ --with-csops add CSOps standard options], +AC_ARG_WITH(csops, [AS_HELP_STRING([--with-csops], [add CSOps standard options])], [case $with_csops in yes) AC_MSG_NOTICE([Adding CSOps standard options]) CHECKSIA=false @@ -277,7 +294,7 @@ AC_ARG_WITH(csops, [ --with-csops add CSOps standard options], ;; esac]) -AC_ARG_WITH(passwd, [ --without-passwd don't use passwd/shadow file for authentication], +AC_ARG_WITH(passwd, [AS_HELP_STRING([--without-passwd], [don't use passwd/shadow file for authentication])], [case $with_passwd in yes|no) AC_MSG_CHECKING(whether to use shadow/passwd file authentication) AC_MSG_RESULT($with_passwd) @@ -288,7 +305,7 @@ AC_ARG_WITH(passwd, [ --without-passwd don't use passwd/shadow file for ;; esac]) -AC_ARG_WITH(skey, [ --with-skey[=DIR] enable S/Key support ], +AC_ARG_WITH(skey, [AS_HELP_STRING([--with-skey[=DIR]], [enable S/Key support ])], [case $with_skey in no) with_skey="" ;; @@ -299,7 +316,7 @@ AC_ARG_WITH(skey, [ --with-skey[=DIR] enable S/Key support ], ;; esac]) -AC_ARG_WITH(opie, [ --with-opie[=DIR] enable OPIE support ], +AC_ARG_WITH(opie, [AS_HELP_STRING([--with-opie[=DIR]], [enable OPIE support ])], [case $with_opie in no) with_opie="" ;; @@ -310,7 +327,7 @@ AC_ARG_WITH(opie, [ --with-opie[=DIR] enable OPIE support ], ;; esac]) -AC_ARG_WITH(long-otp-prompt, [ --with-long-otp-prompt use a two line OTP (skey/opie) prompt], +AC_ARG_WITH(long-otp-prompt, [AS_HELP_STRING([--with-long-otp-prompt], [use a two line OTP (skey/opie) prompt])], [case $with_long_otp_prompt in yes) AC_DEFINE(LONG_OTP_PROMPT) AC_MSG_CHECKING(whether to use a two line prompt for OTP authentication) @@ -323,7 +340,7 @@ AC_ARG_WITH(long-otp-prompt, [ --with-long-otp-prompt use a two line OTP (skey ;; esac]) -AC_ARG_WITH(SecurID, [ --with-SecurID[[=DIR]] enable SecurID support], +AC_ARG_WITH(SecurID, [AS_HELP_STRING([--with-SecurID[[=DIR]]], [enable SecurID support])], [case $with_SecurID in no) with_SecurID="";; *) AC_DEFINE(HAVE_SECURID) @@ -333,7 +350,7 @@ AC_ARG_WITH(SecurID, [ --with-SecurID[[=DIR]] enable SecurID support], ;; esac]) -AC_ARG_WITH(fwtk, [ --with-fwtk[[=DIR]] enable FWTK AuthSRV support], +AC_ARG_WITH(fwtk, [AS_HELP_STRING([--with-fwtk[[=DIR]]], [enable FWTK AuthSRV support])], [case $with_fwtk in no) with_fwtk="";; *) AC_DEFINE(HAVE_FWTK) @@ -343,7 +360,7 @@ AC_ARG_WITH(fwtk, [ --with-fwtk[[=DIR]] enable FWTK AuthSRV support], ;; esac]) -AC_ARG_WITH(kerb4, [ --with-kerb4[[=DIR]] enable Kerberos IV support], +AC_ARG_WITH(kerb4, [AS_HELP_STRING([--with-kerb4[[=DIR]]], [enable Kerberos IV support])], [case $with_kerb4 in no) with_kerb4="";; *) AC_MSG_CHECKING(whether to try kerberos IV authentication) @@ -352,7 +369,7 @@ AC_ARG_WITH(kerb4, [ --with-kerb4[[=DIR]] enable Kerberos IV support], ;; esac]) -AC_ARG_WITH(kerb5, [ --with-kerb5[[=DIR]] enable Kerberos V support], +AC_ARG_WITH(kerb5, [AS_HELP_STRING([--with-kerb5[[=DIR]]], [enable Kerberos V support])], [case $with_kerb5 in no) with_kerb5="";; *) AC_MSG_CHECKING(whether to try Kerberos V authentication) @@ -361,7 +378,7 @@ AC_ARG_WITH(kerb5, [ --with-kerb5[[=DIR]] enable Kerberos V support], ;; esac]) -AC_ARG_WITH(aixauth, [ --with-aixauth enable AIX general authentication support], +AC_ARG_WITH(aixauth, [AS_HELP_STRING([--with-aixauth], [enable AIX general authentication support])], [case $with_aixauth in yes) AUTH_EXCL="$AUTH_EXCL AIX_AUTH";; no) ;; @@ -369,7 +386,7 @@ AC_ARG_WITH(aixauth, [ --with-aixauth enable AIX general authenticatio ;; esac]) -AC_ARG_WITH(pam, [ --with-pam enable PAM support], +AC_ARG_WITH(pam, [AS_HELP_STRING([--with-pam], [enable PAM support])], [case $with_pam in yes) AUTH_EXCL="$AUTH_EXCL PAM";; no) ;; @@ -377,7 +394,7 @@ AC_ARG_WITH(pam, [ --with-pam enable PAM support], ;; esac]) -AC_ARG_WITH(AFS, [ --with-AFS enable AFS support], +AC_ARG_WITH(AFS, [AS_HELP_STRING([--with-AFS], [enable AFS support])], [case $with_AFS in yes) AC_DEFINE(HAVE_AFS) AC_MSG_CHECKING(whether to try AFS (kerberos) authentication) @@ -389,7 +406,7 @@ AC_ARG_WITH(AFS, [ --with-AFS enable AFS support], ;; esac]) -AC_ARG_WITH(DCE, [ --with-DCE enable DCE support], +AC_ARG_WITH(DCE, [AS_HELP_STRING([--with-DCE], [enable DCE support])], [case $with_DCE in yes) AC_DEFINE(HAVE_DCE) AC_MSG_CHECKING(whether to try DCE (kerberos) authentication) @@ -401,14 +418,14 @@ AC_ARG_WITH(DCE, [ --with-DCE enable DCE support], ;; esac]) -AC_ARG_WITH(logincap, [ --with-logincap enable BSD login class support], +AC_ARG_WITH(logincap, [AS_HELP_STRING([--with-logincap], [enable BSD login class support])], [case $with_logincap in yes|no) ;; *) AC_MSG_ERROR(["--with-logincap does not take an argument."]) ;; esac]) -AC_ARG_WITH(bsdauth, [ --with-bsdauth enable BSD authentication support], +AC_ARG_WITH(bsdauth, [AS_HELP_STRING([--with-bsdauth], [enable BSD authentication support])], [case $with_bsdauth in yes) AUTH_EXCL="$AUTH_EXCL BSD_AUTH";; no) ;; @@ -416,7 +433,7 @@ AC_ARG_WITH(bsdauth, [ --with-bsdauth enable BSD authentication suppor ;; esac]) -AC_ARG_WITH(project, [ --with-project enable Solaris project support], +AC_ARG_WITH(project, [AS_HELP_STRING([--with-project], [enable Solaris project support])], [case $with_project in yes|no) ;; no) ;; @@ -425,7 +442,7 @@ AC_ARG_WITH(project, [ --with-project enable Solaris project support], esac]) AC_MSG_CHECKING(whether to lecture users the first time they run sudo) -AC_ARG_WITH(lecture, [ --without-lecture don't print lecture for first-time sudoer], +AC_ARG_WITH(lecture, [AS_HELP_STRING([--without-lecture], [don't print lecture for first-time sudoer])], [case $with_lecture in yes|short|always) lecture=once ;; @@ -442,7 +459,7 @@ else fi AC_MSG_CHECKING(whether sudo should log via syslog or to a file by default) -AC_ARG_WITH(logging, [ --with-logging log via syslog, file, or both], +AC_ARG_WITH(logging, [AS_HELP_STRING([--with-logging], [log via syslog, file, or both])], [case $with_logging in yes) AC_MSG_ERROR(["must give --with-logging an argument."]) ;; @@ -462,7 +479,7 @@ AC_ARG_WITH(logging, [ --with-logging log via syslog, file, or both], esac], [AC_DEFINE(LOGGING, SLOG_SYSLOG) AC_MSG_RESULT(syslog)]) AC_MSG_CHECKING(which syslog facility sudo should log with) -AC_ARG_WITH(logfac, [ --with-logfac syslog facility to log with (default is "local2")], +AC_ARG_WITH(logfac, [AS_HELP_STRING([--with-logfac], [syslog facility to log with (default is "local2")])], [case $with_logfac in yes) AC_MSG_ERROR(["must give --with-logfac an argument."]) ;; @@ -477,7 +494,7 @@ AC_DEFINE_UNQUOTED(LOGFAC, "$logfac", [The syslog facility sudo will use.]) AC_MSG_RESULT($logfac) AC_MSG_CHECKING(at which syslog priority to log commands) -AC_ARG_WITH(goodpri, [ --with-goodpri syslog priority for commands (def is "notice")], +AC_ARG_WITH(goodpri, [AS_HELP_STRING([--with-goodpri], [syslog priority for commands (def is "notice")])], [case $with_goodpri in yes) AC_MSG_ERROR(["must give --with-goodpri an argument."]) ;; @@ -493,7 +510,7 @@ AC_DEFINE_UNQUOTED(PRI_SUCCESS, "$goodpri", [The syslog priority sudo will use f AC_MSG_RESULT($goodpri) AC_MSG_CHECKING(at which syslog priority to log failures) -AC_ARG_WITH(badpri, [ --with-badpri syslog priority for failures (def is "alert")], +AC_ARG_WITH(badpri, [AS_HELP_STRING([--with-badpri], [syslog priority for failures (def is "alert")])], [case $with_badpri in yes) AC_MSG_ERROR(["must give --with-badpri an argument."]) ;; @@ -508,7 +525,7 @@ esac]) AC_DEFINE_UNQUOTED(PRI_FAILURE, "$badpri", [The syslog priority sudo will use for unsuccessful attempts/errors.]) AC_MSG_RESULT($badpri) -AC_ARG_WITH(logpath, [ --with-logpath path to the sudo log file], +AC_ARG_WITH(logpath, [AS_HELP_STRING([--with-logpath], [path to the sudo log file])], [case $with_logpath in yes) AC_MSG_ERROR(["must give --with-logpath an argument."]) ;; @@ -517,7 +534,7 @@ AC_ARG_WITH(logpath, [ --with-logpath path to the sudo log file], esac]) AC_MSG_CHECKING(how long a line in the log file should be) -AC_ARG_WITH(loglen, [ --with-loglen maximum length of a log file line (default is 80)], +AC_ARG_WITH(loglen, [AS_HELP_STRING([--with-loglen], [maximum length of a log file line (default is 80)])], [case $with_loglen in yes) AC_MSG_ERROR(["must give --with-loglen an argument."]) ;; @@ -532,7 +549,7 @@ AC_DEFINE_UNQUOTED(MAXLOGFILELEN, $loglen, [The max number of chars per log file AC_MSG_RESULT($loglen) AC_MSG_CHECKING(whether sudo should ignore '.' or '' in \$PATH) -AC_ARG_WITH(ignore-dot, [ --with-ignore-dot ignore '.' in the PATH], +AC_ARG_WITH(ignore-dot, [AS_HELP_STRING([--with-ignore-dot], [ignore '.' in the PATH])], [case $with_ignore_dot in yes) ignore_dot=on ;; @@ -549,7 +566,7 @@ else fi AC_MSG_CHECKING(whether to send mail when a user is not in sudoers) -AC_ARG_WITH(mail-if-no-user, [ --without-mail-if-no-user do not send mail if user not in sudoers], +AC_ARG_WITH(mail-if-no-user, [AS_HELP_STRING([--without-mail-if-no-user], [do not send mail if user not in sudoers])], [case $with_mail_if_no_user in yes) mail_no_user=on ;; @@ -566,7 +583,7 @@ else fi AC_MSG_CHECKING(whether to send mail when user listed but not for this host) -AC_ARG_WITH(mail-if-no-host, [ --with-mail-if-no-host send mail if user in sudoers but not for this host], +AC_ARG_WITH(mail-if-no-host, [AS_HELP_STRING([--with-mail-if-no-host], [send mail if user in sudoers but not for this host])], [case $with_mail_if_no_host in yes) mail_no_host=on ;; @@ -583,7 +600,7 @@ else fi AC_MSG_CHECKING(whether to send mail when a user tries a disallowed command) -AC_ARG_WITH(mail-if-noperms, [ --with-mail-if-noperms send mail if user not allowed to run command], +AC_ARG_WITH(mail-if-noperms, [AS_HELP_STRING([--with-mail-if-noperms], [send mail if user not allowed to run command])], [case $with_mail_if_noperms in yes) mail_noperms=on ;; @@ -600,7 +617,7 @@ else fi AC_MSG_CHECKING(who should get the mail that sudo sends) -AC_ARG_WITH(mailto, [ --with-mailto who should get sudo mail (default is "root")], +AC_ARG_WITH(mailto, [AS_HELP_STRING([--with-mailto], [who should get sudo mail (default is "root")])], [case $with_mailto in yes) AC_MSG_ERROR(["must give --with-mailto an argument."]) ;; @@ -612,7 +629,7 @@ esac]) AC_DEFINE_UNQUOTED(MAILTO, "$mailto", [The user or email address that sudo mail is sent to.]) AC_MSG_RESULT([$mailto]) -AC_ARG_WITH(mailsubject, [ --with-mailsubject subject of sudo mail], +AC_ARG_WITH(mailsubject, [AS_HELP_STRING([--with-mailsubject], [subject of sudo mail])], [case $with_mailsubject in yes) AC_MSG_ERROR(["must give --with-mailsubject an argument."]) ;; @@ -626,7 +643,7 @@ esac]) AC_DEFINE_UNQUOTED(MAILSUBJECT, "$mailsub", [The subject of the mail sent by sudo to the MAILTO user/address.]) AC_MSG_CHECKING(for bad password prompt) -AC_ARG_WITH(passprompt, [ --with-passprompt default password prompt], +AC_ARG_WITH(passprompt, [AS_HELP_STRING([--with-passprompt], [default password prompt])], [case $with_passprompt in yes) AC_MSG_ERROR(["must give --with-passprompt an argument."]) ;; @@ -638,7 +655,7 @@ AC_MSG_RESULT($passprompt) AC_DEFINE_UNQUOTED(PASSPROMPT, "$passprompt", [The default password prompt.]) AC_MSG_CHECKING(for bad password message) -AC_ARG_WITH(badpass-message, [ --with-badpass-message message the user sees when the password is wrong], +AC_ARG_WITH(badpass-message, [AS_HELP_STRING([--with-badpass-message], [message the user sees when the password is wrong])], [case $with_badpass_message in yes) AC_MSG_ERROR(["Must give --with-badpass-message an argument."]) ;; @@ -651,7 +668,7 @@ AC_DEFINE_UNQUOTED(INCORRECT_PASSWORD, "$badpass_message", [The message given wh AC_MSG_RESULT([$badpass_message]) AC_MSG_CHECKING(whether to expect fully qualified hosts in sudoers) -AC_ARG_WITH(fqdn, [ --with-fqdn expect fully qualified hosts in sudoers], +AC_ARG_WITH(fqdn, [AS_HELP_STRING([--with-fqdn], [expect fully qualified hosts in sudoers])], [case $with_fqdn in yes) fqdn=on ;; @@ -667,7 +684,7 @@ else AC_MSG_RESULT(no) fi -AC_ARG_WITH(timedir, [ --with-timedir path to the sudo timestamp dir], +AC_ARG_WITH(timedir, [AS_HELP_STRING([--with-timedir], [path to the sudo timestamp dir])], [case $with_timedir in yes) AC_MSG_ERROR(["must give --with-timedir an argument."]) ;; @@ -675,8 +692,8 @@ AC_ARG_WITH(timedir, [ --with-timedir path to the sudo timestamp dir], ;; esac]) -AC_ARG_WITH(sendmail, [ --with-sendmail=path set path to sendmail - --without-sendmail do not send mail at all], +AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail]) +AS_HELP_STRING([--without-sendmail], [do not send mail at all])], [case $with_sendmail in yes) with_sendmail="" ;; @@ -685,7 +702,7 @@ AC_ARG_WITH(sendmail, [ --with-sendmail=path set path to sendmail ;; esac]) -AC_ARG_WITH(sudoers-mode, [ --with-sudoers-mode mode of sudoers file (defaults to 0440)], +AC_ARG_WITH(sudoers-mode, [AS_HELP_STRING([--with-sudoers-mode], [mode of sudoers file (defaults to 0440)])], [case $with_sudoers_mode in yes) AC_MSG_ERROR(["must give --with-sudoers-mode an argument."]) ;; @@ -699,7 +716,7 @@ AC_ARG_WITH(sudoers-mode, [ --with-sudoers-mode mode of sudoers file (defau ;; esac]) -AC_ARG_WITH(sudoers-uid, [ --with-sudoers-uid uid that owns sudoers file (defaults to 0)], +AC_ARG_WITH(sudoers-uid, [AS_HELP_STRING([--with-sudoers-uid], [uid that owns sudoers file (defaults to 0)])], [case $with_sudoers_uid in yes) AC_MSG_ERROR(["must give --with-sudoers-uid an argument."]) ;; @@ -711,7 +728,7 @@ AC_ARG_WITH(sudoers-uid, [ --with-sudoers-uid uid that owns sudoers file ( ;; esac]) -AC_ARG_WITH(sudoers-gid, [ --with-sudoers-gid gid that owns sudoers file (defaults to 0)], +AC_ARG_WITH(sudoers-gid, [AS_HELP_STRING([--with-sudoers-gid], [gid that owns sudoers file (defaults to 0)])], [case $with_sudoers_gid in yes) AC_MSG_ERROR(["must give --with-sudoers-gid an argument."]) ;; @@ -724,8 +741,8 @@ AC_ARG_WITH(sudoers-gid, [ --with-sudoers-gid gid that owns sudoers file ( esac]) AC_MSG_CHECKING(for umask programs should be run with) -AC_ARG_WITH(umask, [ --with-umask umask with which the prog should run (default is 022) - --without-umask Preserves the umask of the user invoking sudo.], +AC_ARG_WITH(umask, [AS_HELP_STRING([--with-umask], [umask with which the prog should run (default is 022)]) +AS_HELP_STRING([--without-umask], [Preserves the umask of the user invoking sudo.])], [case $with_umask in yes) AC_MSG_ERROR(["must give --with-umask an argument."]) ;; @@ -744,7 +761,7 @@ else fi AC_MSG_CHECKING(for default user to run commands as) -AC_ARG_WITH(runas-default, [ --with-runas-default User to run commands as (default is "root")], +AC_ARG_WITH(runas-default, [AS_HELP_STRING([--with-runas-default], [User to run commands as (default is "root")])], [case $with_runas_default in yes) AC_MSG_ERROR(["must give --with-runas-default an argument."]) ;; @@ -756,7 +773,7 @@ esac]) AC_DEFINE_UNQUOTED(RUNAS_DEFAULT, "$runas_default", [The user sudo should run commands as by default.]) AC_MSG_RESULT([$runas_default]) -AC_ARG_WITH(exempt, [ --with-exempt=group no passwd needed for users in this group], +AC_ARG_WITH(exempt, [AS_HELP_STRING([--with-exempt=group], [no passwd needed for users in this group])], [case $with_exempt in yes) AC_MSG_ERROR(["must give --with-exempt an argument."]) ;; @@ -769,7 +786,7 @@ AC_ARG_WITH(exempt, [ --with-exempt=group no passwd needed for users in thi esac]) AC_MSG_CHECKING(for editor that visudo should use) -AC_ARG_WITH(editor, [ --with-editor=path Default editor for visudo (defaults to vi)], +AC_ARG_WITH(editor, [AS_HELP_STRING([--with-editor=path], [Default editor for visudo (defaults to vi)])], [case $with_editor in yes) AC_MSG_ERROR(["must give --with-editor an argument."]) ;; @@ -781,7 +798,7 @@ AC_ARG_WITH(editor, [ --with-editor=path Default editor for visudo (defaul esac], [AC_DEFINE(EDITOR, _PATH_VI) AC_MSG_RESULT(vi)]) AC_MSG_CHECKING(whether to obey EDITOR and VISUAL environment variables) -AC_ARG_WITH(env-editor, [ --with-env-editor Use the environment variable EDITOR for visudo], +AC_ARG_WITH(env-editor, [AS_HELP_STRING([--with-env-editor], [Use the environment variable EDITOR for visudo])], [case $with_env_editor in yes) env_editor=on ;; @@ -798,7 +815,7 @@ else fi AC_MSG_CHECKING(number of tries a user gets to enter their password) -AC_ARG_WITH(passwd-tries, [ --with-passwd-tries number of tries to enter password (default is 3)], +AC_ARG_WITH(passwd-tries, [AS_HELP_STRING([--with-passwd-tries], [number of tries to enter password (default is 3)])], [case $with_passwd_tries in yes) ;; no) AC_MSG_ERROR(["--without-editor not supported."]) @@ -812,7 +829,7 @@ AC_DEFINE_UNQUOTED(TRIES_FOR_PASSWORD, $passwd_tries, [The number of tries a use AC_MSG_RESULT($passwd_tries) AC_MSG_CHECKING(time in minutes after which sudo will ask for a password again) -AC_ARG_WITH(timeout, [ --with-timeout minutes before sudo asks for passwd again (def is 5 minutes)], +AC_ARG_WITH(timeout, [AS_HELP_STRING([--with-timeout], [minutes before sudo asks for passwd again (def is 5 minutes)])], [case $with_timeout in yes) ;; no) timeout=0 @@ -826,7 +843,7 @@ AC_DEFINE_UNQUOTED(TIMEOUT, $timeout, [The number of minutes before sudo asks fo AC_MSG_RESULT($timeout) AC_MSG_CHECKING(time in minutes after the password prompt will time out) -AC_ARG_WITH(password-timeout, [ --with-password-timeout passwd prompt timeout in minutes (default is 5 minutes)], +AC_ARG_WITH(password-timeout, [AS_HELP_STRING([--with-password-timeout], [passwd prompt timeout in minutes (default is 5 minutes)])], [case $with_password_timeout in yes) ;; no) password_timeout=0 @@ -840,7 +857,7 @@ AC_DEFINE_UNQUOTED(PASSWORD_TIMEOUT, $password_timeout, [The passwd prompt timeo AC_MSG_RESULT($password_timeout) AC_MSG_CHECKING(whether to use per-tty ticket files) -AC_ARG_WITH(tty-tickets, [ --with-tty-tickets use a different ticket file for each tty], +AC_ARG_WITH(tty-tickets, [AS_HELP_STRING([--with-tty-tickets], [use a different ticket file for each tty])], [case $with_tty_tickets in yes) tty_tickets=on ;; @@ -857,7 +874,7 @@ else fi AC_MSG_CHECKING(whether to include insults) -AC_ARG_WITH(insults, [ --with-insults insult the user for entering an incorrect password], +AC_ARG_WITH(insults, [AS_HELP_STRING([--with-insults], [insult the user for entering an incorrect password])], [case $with_insults in yes) insults=on with_classic_insults=yes @@ -875,7 +892,7 @@ else AC_MSG_RESULT(no) fi -AC_ARG_WITH(all-insults, [ --with-all-insults include all the sudo insult sets], +AC_ARG_WITH(all-insults, [AS_HELP_STRING([--with-all-insults], [include all the sudo insult sets])], [case $with_all_insults in yes) with_classic_insults=yes with_csops_insults=yes @@ -887,7 +904,7 @@ AC_ARG_WITH(all-insults, [ --with-all-insults include all the sudo insult ;; esac]) -AC_ARG_WITH(classic-insults, [ --with-classic-insults include the insults from the "classic" sudo], +AC_ARG_WITH(classic-insults, [AS_HELP_STRING([--with-classic-insults], [include the insults from the "classic" sudo])], [case $with_classic_insults in yes) AC_DEFINE(CLASSIC_INSULTS) ;; @@ -896,7 +913,7 @@ AC_ARG_WITH(classic-insults, [ --with-classic-insults include the insults from ;; esac]) -AC_ARG_WITH(csops-insults, [ --with-csops-insults include CSOps insults], +AC_ARG_WITH(csops-insults, [AS_HELP_STRING([--with-csops-insults], [include CSOps insults])], [case $with_csops_insults in yes) AC_DEFINE(CSOPS_INSULTS) ;; @@ -905,7 +922,7 @@ AC_ARG_WITH(csops-insults, [ --with-csops-insults include CSOps insults], ;; esac]) -AC_ARG_WITH(hal-insults, [ --with-hal-insults include 2001-like insults], +AC_ARG_WITH(hal-insults, [AS_HELP_STRING([--with-hal-insults], [include 2001-like insults])], [case $with_hal_insults in yes) AC_DEFINE(HAL_INSULTS) ;; @@ -914,7 +931,7 @@ AC_ARG_WITH(hal-insults, [ --with-hal-insults include 2001-like insults], ;; esac]) -AC_ARG_WITH(goons-insults, [ --with-goons-insults include the insults from the "Goon Show"], +AC_ARG_WITH(goons-insults, [AS_HELP_STRING([--with-goons-insults], [include the insults from the "Goon Show"])], [case $with_goons_insults in yes) AC_DEFINE(GOONS_INSULTS) ;; @@ -923,38 +940,32 @@ AC_ARG_WITH(goons-insults, [ --with-goons-insults include the insults from t ;; esac]) -AC_ARG_WITH(nsswitch, [ --with-nsswitch[[=PATH]] path to nsswitch.conf], +AC_ARG_WITH(nsswitch, [AS_HELP_STRING([--with-nsswitch[[=PATH]]], [path to nsswitch.conf])], [case $with_nsswitch in no) ;; yes) with_nsswitch="/etc/nsswitch.conf" ;; *) ;; esac]) -if test ${with_nsswitch-"yes"} != "no"; then - SUDO_DEFINE_UNQUOTED(_PATH_NSSWITCH_CONF, "${with_nsswitch-/etc/nsswitch.conf}") - nsswitch_conf=${with_nsswitch-/etc/nsswitch.conf} -else - nsswitch_conf='/etc/nsswitch.conf' -fi -AC_ARG_WITH(ldap, [ --with-ldap[[=DIR]] enable LDAP support], +AC_ARG_WITH(ldap, [AS_HELP_STRING([--with-ldap[[=DIR]]], [enable LDAP support])], [case $with_ldap in - no) with_ldap="";; + no) ;; *) AC_DEFINE(HAVE_LDAP) AC_MSG_CHECKING(whether to use sudoers from LDAP) AC_MSG_RESULT(yes) ;; esac]) -AC_ARG_WITH(ldap-conf-file, [ --with-ldap-conf-file path to LDAP configuration file]) +AC_ARG_WITH(ldap-conf-file, [AS_HELP_STRING([--with-ldap-conf-file], [path to LDAP configuration file])]) SUDO_DEFINE_UNQUOTED(_PATH_LDAP_CONF, "${with_ldap_conf_file-/etc/ldap.conf}", [Path to the ldap.conf file]) ldap_conf=${with_ldap_conf_file-'/etc/ldap.conf'} -AC_ARG_WITH(ldap-secret-file, [ --with-ldap-secret-file path to LDAP secret password file]) +AC_ARG_WITH(ldap-secret-file, [AS_HELP_STRING([--with-ldap-secret-file], [path to LDAP secret password file])]) SUDO_DEFINE_UNQUOTED(_PATH_LDAP_SECRET, "${with_ldap_secret_file-/etc/ldap.secret}", [Path to the ldap.secret file]) ldap_secret=${with_ldap_secret_file-'/etc/ldap.secret'} -AC_ARG_WITH(pc-insults, [ --with-pc-insults replace politically incorrect insults with less offensive ones], +AC_ARG_WITH(pc-insults, [AS_HELP_STRING([--with-pc-insults], [replace politically incorrect insults with less offensive ones])], [case $with_pc_insults in yes) AC_DEFINE(PC_INSULTS) ;; @@ -975,7 +986,7 @@ if test "$insults" = "on"; then fi AC_MSG_CHECKING(whether to override the user's path) -AC_ARG_WITH(secure-path, [ --with-secure-path override the user's path with a built-in one], +AC_ARG_WITH(secure-path, [AS_HELP_STRING([--with-secure-path], [override the user's path with a built-in one])], [case $with_secure_path in yes) AC_DEFINE_UNQUOTED(SECURE_PATH, "/bin:/usr/ucb:/usr/bin:/usr/sbin:/sbin:/usr/etc:/etc") AC_MSG_RESULT([:/usr/ucb:/usr/bin:/usr/sbin:/sbin:/usr/etc:/etc]) @@ -988,7 +999,7 @@ AC_ARG_WITH(secure-path, [ --with-secure-path override the user's path wit esac], AC_MSG_RESULT(no)) AC_MSG_CHECKING(whether to get ip addresses from the network interfaces) -AC_ARG_WITH(interfaces, [ --without-interfaces don't try to read the ip addr of ether interfaces], +AC_ARG_WITH(interfaces, [AS_HELP_STRING([--without-interfaces], [don't try to read the ip addr of ether interfaces])], [case $with_interfaces in yes) AC_MSG_RESULT(yes) ;; @@ -1000,7 +1011,7 @@ AC_ARG_WITH(interfaces, [ --without-interfaces don't try to read the ip addr esac], AC_MSG_RESULT(yes)) AC_MSG_CHECKING(whether stow should be used) -AC_ARG_WITH(stow, [ --with-stow properly handle GNU stow packaging], +AC_ARG_WITH(stow, [AS_HELP_STRING([--with-stow], [properly handle GNU stow packaging])], [case $with_stow in yes) AC_MSG_RESULT(yes) AC_DEFINE(USE_STOW) @@ -1012,7 +1023,7 @@ AC_ARG_WITH(stow, [ --with-stow properly handle GNU stow packaging] esac], AC_MSG_RESULT(no)) AC_MSG_CHECKING(whether to use an askpass helper) -AC_ARG_WITH(askpass, [ --with-askpass=PATH Fully qualified pathname of askpass helper], +AC_ARG_WITH(askpass, [AS_HELP_STRING([--with-askpass=PATH], [Fully qualified pathname of askpass helper])], [case $with_askpass in yes) AC_MSG_ERROR(["--with-askpass takes a path as an argument."]) ;; @@ -1021,14 +1032,36 @@ AC_ARG_WITH(askpass, [ --with-askpass=PATH Fully qualified pathname of askp ;; esac], AC_MSG_RESULT(no)) +dnl +dnl If enabled, set LIBVAS_SO, LIBVAS_RPATH and USING_NONUNIX_GROUPS +dnl +AC_ARG_WITH(libvas, [AS_HELP_STRING([--with-libvas=NAME], [Name of the libvas shared library (default=libvas.so)])], +[case $with_libvas in + yes) with_libvas=libvas.so + ;; + no) ;; + *) AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_with_libvas"], [The name of libvas.so]) + ;; +esac +if test X"$with_libvas" != X"no"; then + AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_libvas"], [The name of libvas.so]) + AC_DEFINE(USING_NONUNIX_GROUPS) + NONUNIX_GROUPS_IMPL="vasgroups.o" + AC_ARG_WITH([libvas-rpath], + [AS_HELP_STRING([--with-libvas-rpath=PATH], + [Path to look for libvas in [default=/opt/quest/lib]])], + [LIBVAS_RPATH=$withval], + [LIBVAS_RPATH=/opt/quest/lib]) +fi +]) + dnl dnl Options for --enable dnl AC_MSG_CHECKING(whether to do user authentication by default) AC_ARG_ENABLE(authentication, -[ --disable-authentication - Do not require authentication by default], +[AS_HELP_STRING([--disable-authentication], [Do not require authentication by default])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) ;; @@ -1043,7 +1076,7 @@ AC_ARG_ENABLE(authentication, AC_MSG_CHECKING(whether to disable running the mailer as root) AC_ARG_ENABLE(root-mailer, -[ --disable-root-mailer Don't run the mailer as root, run as the user], +[AS_HELP_STRING([--disable-root-mailer], [Don't run the mailer as root, run as the user])], [ case "$enableval" in yes) AC_MSG_RESULT(no) ;; @@ -1057,7 +1090,7 @@ AC_ARG_ENABLE(root-mailer, ], AC_MSG_RESULT(no)) AC_ARG_ENABLE(setreuid, -[ --disable-setreuid Don't try to use the setreuid() function], +[AS_HELP_STRING([--disable-setreuid], [Don't try to use the setreuid() function])], [ case "$enableval" in no) SKIP_SETREUID=yes ;; @@ -1066,7 +1099,7 @@ AC_ARG_ENABLE(setreuid, ]) AC_ARG_ENABLE(setresuid, -[ --disable-setresuid Don't try to use the setresuid() function], +[AS_HELP_STRING([--disable-setresuid], [Don't try to use the setresuid() function])], [ case "$enableval" in no) SKIP_SETRESUID=yes ;; @@ -1076,7 +1109,7 @@ AC_ARG_ENABLE(setresuid, AC_MSG_CHECKING(whether to disable shadow password support) AC_ARG_ENABLE(shadow, -[ --disable-shadow Never use shadow passwords], +[AS_HELP_STRING([--disable-shadow], [Never use shadow passwords])], [ case "$enableval" in yes) AC_MSG_RESULT(no) ;; @@ -1091,7 +1124,7 @@ AC_ARG_ENABLE(shadow, AC_MSG_CHECKING(whether root should be allowed to use sudo) AC_ARG_ENABLE(root-sudo, -[ --disable-root-sudo Don't allow root to run sudo], +[AS_HELP_STRING([--disable-root-sudo], [Don't allow root to run sudo])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) ;; @@ -1106,7 +1139,7 @@ AC_ARG_ENABLE(root-sudo, AC_MSG_CHECKING(whether to log the hostname in the log file) AC_ARG_ENABLE(log-host, -[ --enable-log-host Log the hostname in the log file], +[AS_HELP_STRING([--enable-log-host], [Log the hostname in the log file])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_DEFINE(HOST_IN_LOG) @@ -1121,7 +1154,7 @@ AC_ARG_ENABLE(log-host, AC_MSG_CHECKING(whether to invoke a shell if sudo is given no arguments) AC_ARG_ENABLE(noargs-shell, -[ --enable-noargs-shell If sudo is given no arguments run a shell], +[AS_HELP_STRING([--enable-noargs-shell], [If sudo is given no arguments run a shell])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_DEFINE(SHELL_IF_NO_ARGS) @@ -1136,8 +1169,7 @@ AC_ARG_ENABLE(noargs-shell, AC_MSG_CHECKING(whether to set \$HOME to target user in shell mode) AC_ARG_ENABLE(shell-sets-home, -[ --enable-shell-sets-home - Set $HOME to target user in shell mode], +[AS_HELP_STRING([--enable-shell-sets-home], [Set $HOME to target user in shell mode])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_DEFINE(SHELL_SETS_HOME) @@ -1152,7 +1184,7 @@ AC_ARG_ENABLE(shell-sets-home, AC_MSG_CHECKING(whether to disable 'command not found' messages) AC_ARG_ENABLE(path_info, -[ --disable-path-info Print 'command not allowed' not 'command not found'], +[AS_HELP_STRING([--disable-path-info], [Print 'command not allowed' not 'command not found'])], [ case "$enableval" in yes) AC_MSG_RESULT(no) ;; @@ -1166,7 +1198,22 @@ AC_ARG_ENABLE(path_info, esac ], AC_MSG_RESULT(no)) -AC_ARG_WITH(selinux, [ --with-selinux enable SELinux support], +AC_MSG_CHECKING(whether to enable environment debugging) +AC_ARG_ENABLE(env_debug, +[AS_HELP_STRING([--enable-env-debug], [Whether to enable environment debugging.])], +[ case "$enableval" in + yes) AC_MSG_RESULT(yes) + AC_DEFINE(ENV_DEBUG) + ;; + no) AC_MSG_RESULT(no) + ;; + *) AC_MSG_RESULT(no) + AC_MSG_WARN([Ignoring unknown argument to --enable-env-debug: $enableval]) + ;; + esac +], AC_MSG_RESULT(no)) + +AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux], [enable SELinux support])], [case $with_selinux in yes) SELINUX_USAGE="[[-r role]] [[-t type]] " AC_DEFINE(HAVE_SELINUX) @@ -1184,8 +1231,9 @@ esac]) dnl dnl gss_krb5_ccache_name() may not work on Heimdal so we don't use it by default dnl -AC_ARG_ENABLE(gss_krb5_ccache_name, [ --enable-gss-krb5-ccache-name - Use GSS-API to set the Kerberos V cred cache name], [check_gss_krb5_ccache_name=$enableval], [check_gss_krb5_ccache_name=no]) +AC_ARG_ENABLE(gss_krb5_ccache_name, +[AS_HELP_STRING([--enable-gss-krb5-ccache-name], [Use GSS-API to set the Kerberos V cred cache name])], +[check_gss_krb5_ccache_name=$enableval], [check_gss_krb5_ccache_name=no]) dnl dnl If we don't have egrep we can't do anything... @@ -1212,8 +1260,8 @@ dnl dnl Libtool magic; enable shared libs and disable static libs dnl AC_CANONICAL_HOST -AC_CANONICAL_TARGET([]) AC_DISABLE_STATIC +AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL dnl @@ -1225,7 +1273,7 @@ else eval _shrext="$shrext_cmds" fi AC_MSG_CHECKING(path to sudo_noexec.so) -AC_ARG_WITH(noexec, [ --with-noexec[=PATH] fully qualified pathname of sudo_noexec.so], +AC_ARG_WITH(noexec, [AS_HELP_STRING([--with-noexec[=PATH]], [fully qualified pathname of sudo_noexec.so])], [case $with_noexec in yes) with_noexec="$libexecdir/sudo_noexec$_shrext" ;; @@ -1334,6 +1382,18 @@ case "$host" in AC_CHECK_FUNCS(authenticate, [AUTH_EXCL_DEF="AIX_AUTH"]) fi + # AIX analog of nsswitch.conf, enabled by default + AC_ARG_WITH(netsvc, [AS_HELP_STRING([--with-netsvc[[=PATH]]], [path to netsvc.conf])], + [case $with_netsvc in + no) ;; + yes) with_netsvc="/etc/netsvc.conf" + ;; + *) ;; + esac]) + if test -z "$with_nsswitch" -a -z "$with_netsvc"; then + with_netsvc="/etc/netsvc.conf" + fi + # AIX-specific functions AC_CHECK_FUNCS(getuserattr) SUDO_OBJS="$SUDO_OBJS aix.o" @@ -1354,6 +1414,19 @@ case "$host" in if test "x$ac_cv_prog_cc_c89" = "xno"; then with_noexec=no fi + + # Use the +DAportable flag if it is supported + _CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS +DAportable" + AC_CACHE_CHECK([whether $CC understands +DAportable], + [sudo_cv_var_daportable], + [AC_TRY_LINK([], [], [sudo_cv_var_daportable=yes], + [sudo_cv_var_daportable=no])] + ) + if test X"$sudo_cv_var_daportable" != X"yes"; then + CFLAGS="$_CFLAGS" + fi + case "$host" in *-*-hpux[1-8].*) AC_DEFINE(BROKEN_SYSLOG) @@ -1396,7 +1469,7 @@ case "$host" in : ${CHECKSIA='true'} AC_MSG_CHECKING(whether to disable sia support on Digital UNIX) AC_ARG_ENABLE(sia, - [ --disable-sia Disable SIA on Digital UNIX], + [AS_HELP_STRING([--disable-sia], [Disable SIA on Digital UNIX])], [ case "$enableval" in yes) AC_MSG_RESULT(no) CHECKSIA=true @@ -1689,6 +1762,7 @@ dnl dnl Program checks dnl AC_PROG_YACC +AC_PATH_PROG([FLEX], [flex], [flex]) SUDO_PROG_MV SUDO_PROG_BSHELL if test -z "$with_sendmail"; then @@ -1762,7 +1836,9 @@ dnl AC_FUNC_GETGROUPS AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \ strftime setrlimit initgroups getgroups fstat gettimeofday \ - setlocale getaddrinfo setsid) + setlocale getaddrinfo setsid setenv) +AC_CHECK_FUNCS(unsetenv, SUDO_FUNC_UNSETENV_VOID) +SUDO_FUNC_PUTENV_CONST if test -z "$SKIP_SETRESUID"; then AC_CHECK_FUNCS(setresuid, [SKIP_SETREUID=yes]) fi @@ -1857,6 +1933,19 @@ AC_CHECK_FUNCS(getprogname, , [ AC_MSG_RESULT($sudo_cv___progname) ]) +dnl +dnl nsswitch.conf and its equivalents +dnl +netsvc_conf='/etc/netsvc.conf' +nsswitch_conf='/etc/nsswitch.conf' +if test ${with_netsvc-"no"} != "no"; then + SUDO_DEFINE_UNQUOTED(_PATH_NETSVC_CONF, "${with_netsvc-/etc/netsvc.conf}") + netsvc_conf=${with_netsvc-/etc/netsvc.conf} +elif test ${with_nsswitch-"yes"} != "no"; then + SUDO_DEFINE_UNQUOTED(_PATH_NSSWITCH_CONF, "${with_nsswitch-/etc/nsswitch.conf}") + nsswitch_conf=${with_nsswitch-/etc/nsswitch.conf} +fi + dnl dnl Mutually exclusive auth checks come first, followed by dnl non-exclusive ones. Note: passwd must be last of all! @@ -1899,7 +1988,7 @@ if test ${with_pam-"no"} != "no"; then AUTH_EXCL=PAM AC_MSG_CHECKING(whether to use PAM session support) AC_ARG_ENABLE(pam_session, - [ --disable-pam-session Disable PAM session support], + [AS_HELP_STRING([--disable-pam-session], [Disable PAM session support])], [ case "$enableval" in yes) AC_MSG_RESULT(yes) ;; @@ -2389,9 +2478,9 @@ if test ${with_ldap-'no'} != "no"; then AC_MSG_RESULT([yes]) AC_DEFINE(HAVE_LBER_H)]) - AC_CHECK_FUNCS(ldap_initialize ldap_start_tls_s ldap_sasl_interactive_bind_s ldapssl_init ldapssl_set_strength ldap_search_ext_s ldap_unbind_ext_s ldap_str2dn ldap_create ldap_sasl_bind_s) - AC_CHECK_HEADERS([sasl/sasl.h]) + AC_CHECK_HEADERS([sasl/sasl.h] [sasl.h], [AC_CHECK_FUNCS(ldap_sasl_interactive_bind_s)], [break]) AC_CHECK_HEADERS([ldap_ssl.h] [mps/ldap_ssl.h], [break], [], [#include ]) + AC_CHECK_FUNCS(ldap_initialize ldap_start_tls_s ldapssl_init ldapssl_set_strength ldap_search_ext_s ldap_unbind_ext_s ldap_str2dn ldap_create ldap_sasl_bind_s ldap_ssl_client_init ldap_start_tls_s_np) if test X"$check_gss_krb5_ccache_name" = X"yes"; then AC_CHECK_LIB(gssapi, gss_krb5_ccache_name, @@ -2425,6 +2514,18 @@ if test ${with_ldap-'no'} != "no"; then LDFLAGS="$_LDFLAGS" fi +dnl +dnl Add LIBVAS_RPATH to LDFLAGS +dnl GNU ld accepts -R/path/ as an alias for -rpath /path/ +dnl +if test X"$LIBVAS_RPATH" != X""; then + if test -n "$blibpath"; then + blibpath_add="${blibpath_add}:$LIBVAS_RPATH" + else + LDFLAGS="$LDFLAGS -R$LIBVAS_RPATH" + fi +fi + dnl dnl Add $blibpath to SUDO_LDFLAGS if specified by the user or if we dnl added -L dirpaths to SUDO_LDFLAGS. @@ -2539,6 +2640,7 @@ AH_TEMPLATE(HAL_INSULTS, [Define to 1 if you want 2001-like insults.]) AH_TEMPLATE(HAVE_AFS, [Define to 1 if you use AFS.]) AH_TEMPLATE(HAVE_AIXAUTH, [Define to 1 if you use AIX general authentication.]) AH_TEMPLATE(HAVE_BSD_AUTH_H, [Define to 1 if you use BSD authentication.]) +AH_TEMPLATE(HAVE_BSM_AUDIT, [Define to 1 to enable BSM auditing.]) AH_TEMPLATE(HAVE_DCE, [Define to 1 if you use OSF DCE.]) AH_TEMPLATE(HAVE_DD_FD, [Define to 1 if your `DIR' contains dd_fd.]) AH_TEMPLATE(HAVE_DIRFD, [Define to 1 if you have the `dirfd' function or macro.]) @@ -2603,6 +2705,7 @@ AH_TEMPLATE(USE_TTY_TICKETS, [Define to 1 if you want a different ticket file fo AH_TEMPLATE(WITHOUT_PASSWD, [Define to avoid using the passwd/shadow file for authentication.]) AH_TEMPLATE(sig_atomic_t, [Define to `int' if does not define.]) AH_TEMPLATE(__signed, [Define to `signed' or nothing if compiler does not support a signed type qualifier.]) +AH_TEMPLATE(USING_NONUNIX_GROUPS, [Define to 1 if using a non-Unix group lookup implementation.]) dnl dnl Bits to copy verbatim into config.h.in diff --git a/def_data.c b/def_data.c index 72c14c9..8498464 100644 --- a/def_data.c +++ b/def_data.c @@ -302,6 +302,18 @@ struct sudo_defs_types sudo_defs_table[] = { "visiblepw", T_FLAG, "Allow sudo to prompt for a password even if it would be visisble", NULL, + }, { + "pwfeedback", T_FLAG, + "Provide visual feedback at the password prompt when there is user input", + NULL, + }, { + "fast_glob", T_FLAG, + "Use faster globbing that is less accurate but does not access the filesystem", + NULL, + }, { + "umask_override", T_FLAG, + "The umask specified in sudoers will override the user's, even if it is more permissive", + NULL, }, { NULL, 0, NULL } diff --git a/def_data.h b/def_data.h index afa78e0..bccfd16 100644 --- a/def_data.h +++ b/def_data.h @@ -138,6 +138,12 @@ #define I_SUDOERS_LOCALE 68 #define def_visiblepw (sudo_defs_table[69].sd_un.flag) #define I_VISIBLEPW 69 +#define def_pwfeedback (sudo_defs_table[70].sd_un.flag) +#define I_PWFEEDBACK 70 +#define def_fast_glob (sudo_defs_table[71].sd_un.flag) +#define I_FAST_GLOB 71 +#define def_umask_override (sudo_defs_table[72].sd_un.flag) +#define I_UMASK_OVERRIDE 72 enum def_tupple { never, diff --git a/def_data.in b/def_data.in index 0a0a3b8..625c140 100644 --- a/def_data.in +++ b/def_data.in @@ -223,3 +223,12 @@ sudoers_locale visiblepw T_FLAG "Allow sudo to prompt for a password even if it would be visisble" +pwfeedback + T_FLAG + "Provide visual feedback at the password prompt when there is user input" +fast_glob + T_FLAG + "Use faster globbing that is less accurate but does not access the filesystem" +umask_override + T_FLAG + "The umask specified in sudoers will override the user's, even if it is more permissive" diff --git a/env.c b/env.c index af6d535..3049dff 100644 --- a/env.c +++ b/env.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005, 2007-2008 + * Copyright (c) 2000-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -43,12 +43,14 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ +#include +#include #include #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: env.c,v 1.94 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: env.c,v 1.106 2009/06/23 18:24:42 millert Exp $"; #endif /* lint */ /* @@ -101,11 +103,8 @@ struct environment { * Prototypes */ void rebuild_env __P((int, int)); -void sudo_setenv __P((const char *, const char *, int)); -void sudo_unsetenv __P((const char *)); -static void _sudo_setenv __P((const char *, const char *, int)); -static void insert_env __P((char *, int, int)); -static void sync_env __P((void)); +static void sudo_setenv __P((const char *, const char *, int)); +static void sudo_putenv __P((char *, int, int)); extern char **environ; /* global environment */ @@ -214,36 +213,13 @@ static const char *initial_keepenv_table[] = { NULL }; -/* - * Syncronize our private copy of the environment with what is - * in environ. - */ -static void -sync_env() -{ - size_t evlen; - char **ep; - - for (ep = environ; *ep != NULL; ep++) - continue; - evlen = ep - environ; - if (evlen + 1 > env.env_size) { - efree(env.envp); - env.env_size = evlen + 1 + 128; - env.envp = emalloc2(env.env_size, sizeof(char *)); - } - memcpy(env.envp, environ, (evlen + 1) * sizeof(char *)); - env.env_len = evlen; - environ = env.envp; -} - /* * Similar to setenv(3) but operates on sudo's private copy of the environment - * and it always overwrites. The dupcheck param determines whether we need - * to verify that the variable is not already set. + * (not environ) and it always overwrites. The dupcheck param determines + * whether we need to verify that the variable is not already set. */ static void -_sudo_setenv(var, val, dupcheck) +sudo_setenv(var, val, dupcheck) const char *var; const char *val; int dupcheck; @@ -261,106 +237,234 @@ _sudo_setenv(var, val, dupcheck) errorx(1, "internal error, sudo_setenv() overflow"); } - insert_env(estring, dupcheck, FALSE); + sudo_putenv(estring, dupcheck, TRUE); } -#ifdef HAVE_LDAP /* - * External version of sudo_setenv() that keeps things in sync with - * the environ pointer. + * Version of setenv(3) that uses our own environ pointer. + * Will sync with environ as needed. */ -void -sudo_setenv(var, val, dupcheck) +int +setenv(var, val, overwrite) const char *var; const char *val; - int dupcheck; + int overwrite; { - char *estring; + char *estring, *ep; + const char *cp; size_t esize; - /* Make sure we are operating on the current environment. */ - if (env.envp != environ) - sync_env(); + if (!var || *var == '\0') + return(EINVAL); - esize = strlen(var) + 1 + strlen(val) + 1; - estring = emalloc(esize); + /* + * POSIX says a var name with '=' is an error but BSD + * just ignores the '=' and anything after it. + */ + for (cp = var; *cp && *cp != '='; cp++) + ; + esize = (size_t)(cp - var) + 2; + if (val) { + esize += strlen(val); /* glibc treats a NULL val as "" */ + } - /* Build environment string and insert it. */ - if (strlcpy(estring, var, esize) >= esize || - strlcat(estring, "=", esize) >= esize || - strlcat(estring, val, esize) >= esize) { + /* Allocate and fill in estring. */ + estring = ep = emalloc(esize); + for (cp = var; *cp && *cp != '='; cp++) + *ep++ = *cp; + *ep++ = '='; + if (val) { + for (cp = val; *cp; cp++) + *ep++ = *cp; + } + *ep = '\0'; - errorx(1, "internal error, sudo_setenv() overflow"); + /* Sync env.envp with environ as needed. */ + if (env.envp != environ) { + char **ep; + size_t len; + + for (ep = environ; *ep != NULL; ep++) + continue; + len = ep - environ; + if (len + 2 > env.env_size) { + efree(env.envp); + env.env_size = len + 2 + 128; + env.envp = emalloc2(env.env_size, sizeof(char *)); +#ifdef ENV_DEBUG + memset(env.envp, 0, env.env_size * sizeof(char *)); +#endif + } + memcpy(env.envp, environ, len * sizeof(char *)); + env.envp[len] = NULL; + env.env_len = len; + environ = env.envp; +#ifdef ENV_DEBUG + } else { + if (env.envp[env.env_len] != NULL) + errorx(1, "setenv: corrupted envp, len mismatch"); +#endif } - insert_env(estring, dupcheck, TRUE); + sudo_putenv(estring, TRUE, overwrite); + return(0); } -#endif /* HAVE_LDAP */ -#if defined(HAVE_LDAP) || defined(HAVE_AIXAUTH) /* - * Similar to unsetenv(3) but operates on sudo's private copy of the - * environment. + * Version of unsetenv(3) that uses our own environ pointer. + * Will sync with environ as needed. */ +#ifdef UNSETENV_VOID void -sudo_unsetenv(var) +#else +int +#endif +unsetenv(var) const char *var; { - char **nep; - size_t varlen; + char **ep; + size_t len; + + if (strchr(var, '=') != NULL) { + errno = EINVAL; +#ifdef UNSETENV_VOID + return; +#else + return(-1); +#endif + } /* Make sure we are operating on the current environment. */ - if (env.envp != environ) - sync_env(); - - varlen = strlen(var); - for (nep = env.envp; *nep; nep++) { - if (strncmp(var, *nep, varlen) == 0 && (*nep)[varlen] == '=') { - /* Found it; move everything over by one and update len. */ - memmove(nep, nep + 1, - (env.env_len - (nep - env.envp)) * sizeof(char *)); + /* XXX - this could be optimized to include the search */ + if (env.envp != environ) { + for (ep = environ; *ep != NULL; ep++) + continue; + len = ep - environ; + if (len + 1 > env.env_size) { + efree(env.envp); + env.env_size = len + 1 + 128; + env.envp = emalloc2(env.env_size, sizeof(char *)); +#ifdef ENV_DEBUG + memset(env.envp, 0, env.env_size * sizeof(char *)); +#endif + } + memcpy(env.envp, environ, len * sizeof(char *)); + env.envp[len] = NULL; + env.env_len = len; + environ = env.envp; +#ifdef ENV_DEBUG + } else { + if (env.envp[env.env_len] != NULL) + errorx(1, "unsetenv: corrupted envp, len mismatch"); +#endif + } + + len = strlen(var); + for (ep = env.envp; *ep; ep++) { + if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') { + /* Found it; shift remainder + NULL over by one and update len. */ + memmove(ep, ep + 1, + (env.env_len - (ep - env.envp)) * sizeof(char *)); env.env_len--; - return; + break; } } +#ifndef UNSETENV_VOID + return(0); +#endif } -#endif /* HAVE_LDAP || HAVE_AIXAUTH */ /* - * Insert str into env.envp, assumes str has an '=' in it. + * Version of putenv(3) that uses our own environ pointer. + * Will sync with environ as needed. + */ +int +#ifdef PUTENV_CONST +putenv(const char *string) +#else +putenv(string) + char *string; +#endif +{ + if (strchr(string, '=') == NULL) { + errno = EINVAL; + return(-1); + } + /* Sync env.envp with environ as needed. */ + if (env.envp != environ) { + char **ep; + size_t len; + + for (ep = environ; *ep != NULL; ep++) + continue; + len = ep - environ; + if (len + 2 > env.env_size) { + efree(env.envp); + env.env_size = len + 2 + 128; + env.envp = emalloc2(env.env_size, sizeof(char *)); +#ifdef ENV_DEBUG + memset(env.envp, 0, env.env_size * sizeof(char *)); +#endif + } + memcpy(env.envp, environ, len * sizeof(char *)); + env.envp[len] = NULL; + env.env_len = len; + environ = env.envp; +#ifdef ENV_DEBUG + } else { + if (env.envp[env.env_len] != NULL) + errorx(1, "putenv: corrupted envp, len mismatch"); +#endif + } + sudo_putenv((char *)string, TRUE, TRUE); + return(0); +} + +/* + * Similar to putenv(3) but operates on sudo's private copy of the + * environment (not environ) and it always overwrites. The dupcheck param + * determines whether we need to verify that the variable is not already set. + * Will only overwrite an existing variable if overwrite is set. */ static void -insert_env(str, dupcheck, dosync) +sudo_putenv(str, dupcheck, overwrite) char *str; int dupcheck; - int dosync; + int overwrite; { - char **nep; - size_t varlen; + char **ep; + size_t len; /* Make sure there is room for the new entry plus a NULL. */ if (env.env_len + 2 > env.env_size) { env.env_size += 128; env.envp = erealloc3(env.envp, env.env_size, sizeof(char *)); - if (dosync) - environ = env.envp; +#ifdef ENV_DEBUG + memset(env.envp + env.env_len, 0, + (env.env_size - env.env_len) * sizeof(char *)); +#endif + environ = env.envp; } - if (dupcheck) { - varlen = (strchr(str, '=') - str) + 1; +#ifdef ENV_DEBUG + if (env.envp[env.env_len] != NULL) + errorx(1, "sudo_putenv: corrupted envp, len mismatch"); +#endif - for (nep = env.envp; *nep; nep++) { - if (strncmp(str, *nep, varlen) == 0) { - if (dupcheck != -1) - *nep = str; + if (dupcheck) { + len = (strchr(str, '=') - str) + 1; + for (ep = env.envp; *ep; ep++) { + if (strncmp(str, *ep, len) == 0) { + if (overwrite) + *ep = str; return; } } } else - nep = env.envp + env.env_len; + ep = env.envp + env.env_len; env.env_len++; - *nep++ = str; - *nep = NULL; + *ep++ = str; + *ep = NULL; } /* @@ -475,6 +579,9 @@ rebuild_env(sudo_mode, noexec) env.env_size = 128; old_envp = env.envp; env.envp = emalloc2(env.env_size, sizeof(char *)); +#ifdef ENV_DEBUG + memset(env.envp, 0, env.env_size * sizeof(char *)); +#endif if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { /* Pull in vars we want to keep from the old environment. */ for (ep = environ; *ep; ep++) { @@ -529,7 +636,7 @@ rebuild_env(sudo_mode, noexec) SET(didvar, DID_USERNAME); break; } - insert_env(*ep, FALSE, FALSE); + sudo_putenv(*ep, FALSE, FALSE); } } didvar |= didvar << 8; /* convert DID_* to KEPT_* */ @@ -540,24 +647,24 @@ rebuild_env(sudo_mode, noexec) * on sudoers options). */ if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { - _sudo_setenv("HOME", runas_pw->pw_dir, ISSET(didvar, DID_HOME)); - _sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL)); - _sudo_setenv("LOGNAME", runas_pw->pw_name, + sudo_setenv("HOME", runas_pw->pw_dir, ISSET(didvar, DID_HOME)); + sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL)); + sudo_setenv("LOGNAME", runas_pw->pw_name, ISSET(didvar, DID_LOGNAME)); - _sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER)); - _sudo_setenv("USERNAME", runas_pw->pw_name, + sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER)); + sudo_setenv("USERNAME", runas_pw->pw_name, ISSET(didvar, DID_USERNAME)); } else { if (!ISSET(didvar, DID_HOME)) - _sudo_setenv("HOME", user_dir, FALSE); + sudo_setenv("HOME", user_dir, FALSE); if (!ISSET(didvar, DID_SHELL)) - _sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); + sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); if (!ISSET(didvar, DID_LOGNAME)) - _sudo_setenv("LOGNAME", user_name, FALSE); + sudo_setenv("LOGNAME", user_name, FALSE); if (!ISSET(didvar, DID_USER)) - _sudo_setenv("USER", user_name, FALSE); + sudo_setenv("USER", user_name, FALSE); if (!ISSET(didvar, DID_USERNAME)) - _sudo_setenv("USERNAME", user_name, FALSE); + sudo_setenv("USERNAME", user_name, FALSE); } } else { /* @@ -588,13 +695,13 @@ rebuild_env(sudo_mode, noexec) SET(didvar, DID_PATH); else if (strncmp(*ep, "TERM=", 5) == 0) SET(didvar, DID_TERM); - insert_env(*ep, FALSE, FALSE); + sudo_putenv(*ep, FALSE, FALSE); } } } /* Replace the PATH envariable with a secure one? */ if (def_secure_path && !user_is_exempt()) { - _sudo_setenv("PATH", def_secure_path, TRUE); + sudo_setenv("PATH", def_secure_path, TRUE); SET(didvar, DID_PATH); } @@ -602,11 +709,11 @@ rebuild_env(sudo_mode, noexec) /* XXX - not needed for MODE_LOGIN_SHELL */ if (def_set_logname && runas_pw->pw_name) { if (!ISSET(didvar, KEPT_LOGNAME)) - _sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); + sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USER)) - _sudo_setenv("USER", runas_pw->pw_name, TRUE); + sudo_setenv("USER", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USERNAME)) - _sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); + sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); } /* Set $HOME for `sudo -H'. Only valid at PERM_FULL_RUNAS. */ @@ -615,14 +722,14 @@ rebuild_env(sudo_mode, noexec) if (ISSET(sudo_mode, MODE_RESET_HOME) || (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home || (ISSET(sudo_mode, MODE_SHELL) && def_set_home)))) - _sudo_setenv("HOME", runas_pw->pw_dir, TRUE); + sudo_setenv("HOME", runas_pw->pw_dir, TRUE); } /* Provide default values for $TERM and $PATH if they are not set. */ if (!ISSET(didvar, DID_TERM)) - insert_env("TERM=unknown", FALSE, FALSE); + sudo_putenv("TERM=unknown", FALSE, FALSE); if (!ISSET(didvar, DID_PATH)) - _sudo_setenv("PATH", _PATH_DEFPATH, FALSE); + sudo_setenv("PATH", _PATH_DEFPATH, FALSE); /* * Preload a noexec file? For a list of LD_PRELOAD-alikes, see @@ -631,18 +738,18 @@ rebuild_env(sudo_mode, noexec) */ if (noexec && def_noexec_file != NULL) { #if defined(__darwin__) || defined(__APPLE__) - _sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); - _sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); + sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); + sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); #else # if defined(__osf__) || defined(__sgi) easprintf(&cp, "%s:DEFAULT", def_noexec_file); - _sudo_setenv("_RLD_LIST", cp, TRUE); + sudo_setenv("_RLD_LIST", cp, TRUE); efree(cp); # else # ifdef _AIX - _sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); + sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); # else - _sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); + sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); # endif /* _AIX */ # endif /* __osf__ || __sgi */ #endif /* __darwin__ || __APPLE__ */ @@ -650,22 +757,22 @@ rebuild_env(sudo_mode, noexec) /* Set PS1 if SUDO_PS1 is set. */ if (ps1 != NULL) - insert_env(ps1, TRUE, FALSE); + sudo_putenv(ps1, TRUE, TRUE); /* Add the SUDO_COMMAND envariable (cmnd + args). */ if (user_args) { easprintf(&cp, "%s %s", user_cmnd, user_args); - _sudo_setenv("SUDO_COMMAND", cp, TRUE); + sudo_setenv("SUDO_COMMAND", cp, TRUE); efree(cp); } else - _sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); + sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ - _sudo_setenv("SUDO_USER", user_name, TRUE); + sudo_setenv("SUDO_USER", user_name, TRUE); snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_uid); - _sudo_setenv("SUDO_UID", idbuf, TRUE); + sudo_setenv("SUDO_UID", idbuf, TRUE); snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_gid); - _sudo_setenv("SUDO_GID", idbuf, TRUE); + sudo_setenv("SUDO_GID", idbuf, TRUE); /* Install new environment. */ environ = env.envp; @@ -681,13 +788,9 @@ insert_env_vars(env_vars) if (env_vars == NULL) return; - /* Make sure we are operating on the current environment. */ - if (env.envp != environ) - sync_env(); - /* Add user-specified environment variables. */ for (cur = env_vars; cur != NULL; cur = cur->next) - insert_env(cur->value, TRUE, TRUE); + putenv(cur->value); } /* @@ -747,35 +850,59 @@ validate_env_vars(env_vars) /* * Read in /etc/environment ala AIX and Linux. - * Lines are in the form of NAME=VALUE + * Lines may be in either of three formats: + * NAME=VALUE + * NAME="VALUE" + * NAME='VALUE' + * with an optional "export" prefix so the shell can source the file. * Invalid lines, blank lines, or lines consisting solely of a comment * character are skipped. */ void -read_env_file(path, replace) +read_env_file(path, overwrite) const char *path; - int replace; + int overwrite; { FILE *fp; - char *cp; + char *cp, *var, *val; + size_t var_len, val_len; if ((fp = fopen(path, "r")) == NULL) return; - /* Make sure we are operating on the current environment. */ - if (env.envp != environ) - sync_env(); - - while ((cp = sudo_parseln(fp)) != NULL) { + while ((var = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ - if (*cp == '\0') + if (*var == '\0') continue; - /* Must be of the form name=value */ - if (strchr(cp, '=') == NULL) + /* Skip optional "export " */ + if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) { + var += 7; + while (isspace((unsigned char) *var)) { + var++; + } + } + + /* Must be of the form name=["']value['"] */ + for (val = var; *val != '\0' && *val != '='; val++) + ; + if (var == val || *val != '=') continue; + var_len = (size_t)(val - var); + val_len = strlen(++val); + + /* Strip leading and trailing single/double quotes */ + if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) { + val[val_len - 1] = '\0'; + val++; + val_len -= 2; + } + + cp = emalloc(var_len + 1 + val_len + 1); + memcpy(cp, var, var_len + 1); /* includes '=' */ + memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */ - insert_env(estrdup(cp), replace ? TRUE : -1, TRUE); + sudo_putenv(cp, TRUE, overwrite); } fclose(fp); } diff --git a/fileops.c b/fileops.c index 9f176bd..40cc860 100644 --- a/fileops.c +++ b/fileops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007 Todd C. Miller + * Copyright (c) 1999-2005,2007,2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -54,7 +54,7 @@ #endif #ifndef lint -__unused static const char rcsid[] = "$Sudo: fileops.c,v 1.16 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: fileops.c,v 1.19 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ /* @@ -144,7 +144,7 @@ lock_file(fd, lockit) lock.l_pid = getpid(); lock.l_type = (lockit == SUDO_UNLOCK) ? F_UNLCK : F_WRLCK; lock.l_whence = SEEK_SET; - func = (lockit == SUDO_TLOCK) ? F_SETLK : F_SETLKW; + func = (lockit == SUDO_LOCK) ? F_SETLKW : F_SETLK; return(fcntl(fd, func, &lock) == 0); #else @@ -172,7 +172,7 @@ sudo_parseln(fp) /* Trim leading and trailing whitespace/newline */ len = strlen(buf); - while (len > 0 && isspace(buf[len - 1])) + while (len > 0 && isspace((unsigned char)buf[len - 1])) buf[--len] = '\0'; for (cp = buf; isblank(*cp); cp++) continue; diff --git a/glob.c b/glob.c index 46d883b..5df33b5 100644 --- a/glob.c +++ b/glob.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Todd C. Miller + * Copyright (c) 2008-2009 Todd C. Miller * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -814,7 +814,7 @@ match(name, pat, patend) return(0); if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; - while (((c = *pat++) & M_MASK) != M_END) + while (((c = *pat++) & M_MASK) != M_END) { if ((c & M_MASK) == M_CLASS) { int idx = *pat & M_MASK; if (idx < NCCLASSES && @@ -828,6 +828,7 @@ match(name, pat, patend) pat += 2; } else if (c == k) ok = 1; + } if (ok == negate_range) return(0); break; diff --git a/gram.c b/gram.c index ed991a7..bcbf25e 100644 --- a/gram.c +++ b/gram.c @@ -73,7 +73,7 @@ static char yyrcsid[] #include "parse.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: gram.c,v 1.34 2008/11/09 14:15:36 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: gram.c,v 1.35 2009/04/18 23:25:08 millert Exp $"; #endif /* lint */ /* @@ -798,15 +798,18 @@ init_parser(path, quiet) init_aliases(); + init_lexer(); + efree(sudoers); sudoers = path ? estrdup(path) : NULL; parse_error = FALSE; errorlineno = -1; + errorfile = NULL; sudolineno = 1; verbose = !quiet; } -#line 758 "y.tab.c" +#line 761 "y.tab.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -1546,7 +1549,7 @@ case 92: yyval.member = new_member(yyvsp[0].string, WORD); } break; -#line 1498 "y.tab.c" +#line 1501 "y.tab.c" } yyssp -= yym; yystate = *yyssp; diff --git a/gram.y b/gram.y index d39068d..9ab395b 100644 --- a/gram.y +++ b/gram.y @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -54,7 +54,7 @@ #include "parse.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: gram.y,v 1.34 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: gram.y,v 1.36 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ /* @@ -766,11 +766,14 @@ init_parser(path, quiet) init_aliases(); + init_lexer(); + efree(sudoers); sudoers = path ? estrdup(path) : NULL; parse_error = FALSE; errorlineno = -1; + errorfile = NULL; sudolineno = 1; verbose = !quiet; } diff --git a/interfaces.c b/interfaces.c index 27ca438..6272704 100644 --- a/interfaces.c +++ b/interfaces.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -85,9 +85,13 @@ struct rtentry; #include "interfaces.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: interfaces.c,v 1.84 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: interfaces.c,v 1.87 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ +/* Minix apparently lacks IFF_LOOPBACK */ +#ifndef IFF_LOOPBACK +# define IFF_LOOPBACK 0 +#endif #ifdef HAVE_GETIFADDRS @@ -139,9 +143,13 @@ load_interfaces() switch(ifa->ifa_addr->sa_family) { case AF_INET: sin = (struct sockaddr_in *)ifa->ifa_addr; + if (sin == NULL) + continue; memcpy(&interfaces[i].addr, &sin->sin_addr, sizeof(struct in_addr)); sin = (struct sockaddr_in *)ifa->ifa_netmask; + if (sin == NULL) + continue; memcpy(&interfaces[i].netmask, &sin->sin_addr, sizeof(struct in_addr)); interfaces[i].family = AF_INET; @@ -150,9 +158,13 @@ load_interfaces() #ifdef HAVE_IN6_ADDR case AF_INET6: sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + if (sin6 == NULL) + continue; memcpy(&interfaces[i].addr, &sin6->sin6_addr, sizeof(struct in6_addr)); sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask; + if (sin6 == NULL) + continue; memcpy(&interfaces[i].netmask, &sin6->sin6_addr, sizeof(struct in6_addr)); interfaces[i].family = AF_INET6; diff --git a/lbuf.c b/lbuf.c index ef898eb..9e6bf0d 100644 --- a/lbuf.c +++ b/lbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008 Todd C. Miller + * Copyright (c) 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -41,12 +41,19 @@ # include #endif /* HAVE_UNISTD_H */ #include +#ifdef HAVE_TERMIOS_H +# include +#else +# ifdef HAVE_TERMIO_H +# include +# endif +#endif #include "sudo.h" #include "lbuf.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: lbuf.c,v 1.7 2008/12/09 20:55:49 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: lbuf.c,v 1.9 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ #if !defined(TIOCGSIZE) && defined(TIOCGWINSZ) diff --git a/ldap.c b/ldap.c index c778f3a..33e6506 100644 --- a/ldap.c +++ b/ldap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Todd C. Miller + * Copyright (c) 2003-2009 Todd C. Miller * * This code is derived from software contributed by Aaron Spangler. * @@ -82,7 +82,7 @@ #include "lbuf.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.100 2008/04/23 12:30:07 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.108 2009/05/29 13:43:12 millert Exp $"; #endif /* lint */ #ifndef LDAP_OPT_SUCCESS @@ -386,10 +386,32 @@ sudo_ldap_init(ldp, host, port) ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2); rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); + /* + * Mozilla-derived SDKs have a bug starting with version 5.0 + * where the path can no longer be a file name and must be a dir. + */ if (rc != LDAP_SUCCESS) { - warningx("unable to initialize SSL cert and key db: %s", - ldapssl_err2string(rc)); - goto done; + char *cp; + if (ldap_conf.tls_certfile) { + cp = strrchr(ldap_conf.tls_certfile, '/'); + if (cp != NULL && strncmp(cp + 1, "cert", 4) == 0) + *cp = '\0'; + } + if (ldap_conf.tls_keyfile) { + cp = strrchr(ldap_conf.tls_keyfile, '/'); + if (cp != NULL && strncmp(cp + 1, "key", 3) == 0) + *cp = '\0'; + } + DPRINTF(("ldapssl_clientauth_init(%s, %s)", + ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", + ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2); + rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, + ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); + if (rc != LDAP_SUCCESS) { + warningx("unable to initialize SSL cert and key db: %s", + ldapssl_err2string(rc)); + goto done; + } } DPRINTF(("ldapssl_init(%s, %d, 1)", host, port), 2); @@ -1128,7 +1150,7 @@ sudo_ldap_display_defaults(nss, pw, lbuf) return(-1); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, - "cn=defaults", NULL, 0, NULL, NULL, NULL, -1, &result); + "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result); if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) { bv = ldap_get_values_len(ld, entry, "sudoOption"); if (bv != NULL) { @@ -1358,7 +1380,7 @@ sudo_ldap_display_privs(nss, pw, lbuf) filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); DPRINTF(("ldap search '%s'", filt), 1); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, - NULL, 0, NULL, NULL, NULL, -1, &result); + NULL, 0, NULL, NULL, NULL, 0, &result); efree(filt); if (rc != LDAP_SUCCESS) continue; /* no entries for this pass */ @@ -1412,7 +1434,7 @@ sudo_ldap_display_cmnd(nss, pw) filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); DPRINTF(("ldap search '%s'", filt), 1); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, - NULL, 0, NULL, NULL, NULL, -1, &result); + NULL, 0, NULL, NULL, NULL, 0, &result); efree(filt); if (rc != LDAP_SUCCESS) continue; /* no entries for this pass */ @@ -1583,7 +1605,7 @@ sudo_ldap_bind_s(ld) DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); } #else - sudo_setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE); + setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE); #endif } rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI", @@ -1594,9 +1616,9 @@ sudo_ldap_bind_s(ld) DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); #else if (old_ccname != NULL) - sudo_setenv("KRB5CCNAME", old_ccname, TRUE); + setenv("KRB5CCNAME", old_ccname, TRUE); else - sudo_unsetenv("KRB5CCNAME"); + unsetenv("KRB5CCNAME"); #endif } if (rc != LDAP_SUCCESS) { @@ -1651,7 +1673,7 @@ sudo_ldap_open(nss) /* Prevent reading of user ldaprc and system defaults. */ if (getenv("LDAPNOINIT") == NULL) { ldapnoinit = TRUE; - sudo_setenv("LDAPNOINIT", "1", TRUE); + setenv("LDAPNOINIT", "1", TRUE); } /* Connect to LDAP server */ @@ -1668,23 +1690,34 @@ sudo_ldap_open(nss) } if (ldapnoinit) - sudo_unsetenv("LDAPNOINIT"); + unsetenv("LDAPNOINIT"); /* Set LDAP options */ if (sudo_ldap_set_options(ld) < 0) return(-1); if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { -#ifdef HAVE_LDAP_START_TLS_S +#if defined(HAVE_LDAP_START_TLS_S) rc = ldap_start_tls_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { warningx("ldap_start_tls_s(): %s", ldap_err2string(rc)); return(-1); } DPRINTF(("ldap_start_tls_s() ok"), 1); +#elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP) + if (ldap_ssl_client_init(NULL, NULL, 0, &rc) != LDAP_SUCCESS) { + warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc)); + return(-1); + } + rc = ldap_start_tls_s_np(ld, NULL); + if (rc != LDAP_SUCCESS) { + warningx("ldap_start_tls_s_np(): %s", ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_start_tls_s_np() ok"), 1); #else - warningx("start_tls specified but LDAP libs do not support ldap_start_tls_s()"); -#endif /* HAVE_LDAP_START_TLS_S */ + warningx("start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"); +#endif /* !HAVE_LDAP_START_TLS_S && !HAVE_LDAP_START_TLS_S_NP */ } /* Actually connect */ @@ -1707,7 +1740,7 @@ sudo_ldap_setdefs(nss) return(-1); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, - "cn=defaults", NULL, 0, NULL, NULL, NULL, -1, &result); + "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result); if (rc == 0 && (entry = ldap_first_entry(ld, result))) { DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); sudo_ldap_parse_options(ld, entry); @@ -1748,7 +1781,7 @@ sudo_ldap_lookup(nss, ret, pwflag) for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) { filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, - NULL, 0, NULL, NULL, NULL, -1, &result); + NULL, 0, NULL, NULL, NULL, 0, &result); efree(filt); if (rc != LDAP_SUCCESS) continue; @@ -1819,7 +1852,7 @@ sudo_ldap_lookup(nss, ret, pwflag) filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); DPRINTF(("ldap search '%s'", filt), 1); rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, - NULL, 0, NULL, NULL, NULL, -1, &result); + NULL, 0, NULL, NULL, NULL, 0, &result); if (rc != LDAP_SUCCESS) DPRINTF(("nothing found for '%s'", filt), 1); efree(filt); diff --git a/logging.c b/logging.c index b536305..53288e5 100644 --- a/logging.c +++ b/logging.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996, 1998-2008 Todd C. Miller + * Copyright (c) 1994-1996, 1998-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -58,7 +58,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: logging.c,v 1.203 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: logging.c,v 1.205 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ static void do_syslog __P((int, char *)); @@ -371,7 +371,7 @@ log_error(flags, fmt, va_alist) #endif /* Become root if we are not already to avoid user interference */ - set_perms(PERM_ROOT); + set_perms(PERM_ROOT|PERM_NOEXIT); /* Expand printf-style format + args. */ evasprintf(&message, fmt, ap); @@ -555,10 +555,10 @@ send_mail(line) * (so user cannot kill it) or as the user (for the paranoid). */ #ifndef NO_ROOT_MAILER - set_perms(PERM_ROOT); + set_perms(PERM_ROOT|PERM_NOEXIT); execve(mpath, argv, root_envp); #else - set_perms(PERM_FULL_USER); + set_perms(PERM_FULL_USER|PERM_NOEXIT); execv(mpath, argv); #endif /* NO_ROOT_MAILER */ mysyslog(LOG_ERR, "cannot execute %s: %m", mpath); diff --git a/logging.h b/logging.h index b3f4941..d65a8ab 100644 --- a/logging.h +++ b/logging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008 + * Copyright (c) 1999-2005, 2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Sudo: logging.h,v 1.13 2008/11/09 14:13:12 millert Exp $ + * $Sudo: logging.h,v 1.15 2009/05/25 12:02:41 millert Exp $ */ #ifndef _LOGGING_H @@ -49,6 +49,8 @@ # define MAXSYSLOGLEN 960 #endif +void audit_success __P((char **)); +void audit_failure __P((char **, char const * const, ...)); void log_allowed __P((int)); void log_denial __P((int, int)); void log_error __P((int flags, const char *fmt, ...)) diff --git a/match.c b/match.c index b3b7f9a..fd60fdb 100644 --- a/match.c +++ b/match.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -89,14 +89,20 @@ #ifndef HAVE_EXTENDED_GLOB # include "emul/glob.h" #endif /* HAVE_EXTENDED_GLOB */ +#ifdef USING_NONUNIX_GROUPS +# include "nonunix.h" +#endif /* USING_NONUNIX_GROUPS */ #ifndef lint -__unused static const char rcsid[] = "$Sudo: match.c,v 1.38 2008/11/02 14:35:37 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: match.c,v 1.46 2009/05/27 00:49:07 millert Exp $"; #endif /* lint */ static struct member_list empty; static int command_matches_dir __P((char *, size_t)); +static int command_matches_glob __P((char *, char *)); +static int command_matches_fnmatch __P((char *, char *)); +static int command_matches_normal __P((char *, char *)); /* * Returns TRUE if string 's' contains meta characters. @@ -130,7 +136,7 @@ _userlist_matches(pw, list) matched = !m->negated; break; case ALIAS: - if ((a = find_alias(m->name, USERALIAS)) != NULL) { + if ((a = alias_find(m->name, USERALIAS)) != NULL) { rval = _userlist_matches(pw, &a->members); if (rval != UNSPEC) matched = m->negated ? !rval : rval; @@ -171,9 +177,13 @@ _runaslist_matches(user_list, group_list) struct alias *a; int rval, matched = UNSPEC; - /* Deny if user specified a group but there is no group in sudoers */ - if (runas_gr != NULL && tq_empty(group_list)) - return(DENY); + if (runas_gr != NULL) { + if (tq_empty(group_list)) + return(DENY); /* group was specified but none in sudoers */ + if (runas_pw != NULL && strcmp(runas_pw->pw_name, user_name) && + tq_empty(user_list)) + return(DENY); /* user was specified but none in sudoers */ + } if (tq_empty(user_list) && tq_empty(group_list)) return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); @@ -193,7 +203,7 @@ _runaslist_matches(user_list, group_list) matched = !m->negated; break; case ALIAS: - if ((a = find_alias(m->name, RUNASALIAS)) != NULL) { + if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { rval = _runaslist_matches(&a->members, &empty); if (rval != UNSPEC) matched = m->negated ? !rval : rval; @@ -217,7 +227,7 @@ _runaslist_matches(user_list, group_list) matched = !m->negated; break; case ALIAS: - if ((a = find_alias(m->name, RUNASALIAS)) != NULL) { + if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { rval = _runaslist_matches(&a->members, &empty); if (rval != UNSPEC) matched = m->negated ? !rval : rval; @@ -273,7 +283,7 @@ _hostlist_matches(list) matched = !m->negated; break; case ALIAS: - if ((a = find_alias(m->name, HOSTALIAS)) != NULL) { + if ((a = alias_find(m->name, HOSTALIAS)) != NULL) { rval = _hostlist_matches(&a->members); if (rval != UNSPEC) matched = m->negated ? !rval : rval; @@ -346,7 +356,7 @@ cmnd_matches(m) break; case ALIAS: alias_seqno++; - if ((a = find_alias(m->name, CMNDALIAS)) != NULL) { + if ((a = alias_find(m->name, CMNDALIAS)) != NULL) { rval = _cmndlist_matches(&a->members); if (rval != UNSPEC) matched = m->negated ? !rval : rval; @@ -370,11 +380,6 @@ command_matches(sudoers_cmnd, sudoers_args) char *sudoers_cmnd; char *sudoers_args; { - struct stat sudoers_stat; - char **ap, *base, *cp; - glob_t gl; - size_t dlen; - /* Check for pseudo-commands */ if (strchr(user_cmnd, '/') == NULL) { /* @@ -396,110 +401,163 @@ command_matches(sudoers_cmnd, sudoers_args) } else return(FALSE); } - dlen = strlen(sudoers_cmnd); - /* - * If sudoers_cmnd has meta characters in it, we may need to - * use glob(3) and fnmatch(3) to do the matching. - */ if (has_meta(sudoers_cmnd)) { /* - * First check to see if we can avoid the call to glob(3). - * Short circuit if there are no meta chars in the command itself - * and user_base and basename(sudoers_cmnd) don't match. - */ - if (sudoers_cmnd[dlen - 1] != '/') { - if ((base = strrchr(sudoers_cmnd, '/')) != NULL) { - base++; - if (!has_meta(base) && strcmp(user_base, base) != 0) - return(FALSE); - } - } - /* - * Return true if we find a match in the glob(3) results AND - * a) there are no args in sudoers OR - * b) there are no args on command line and none required by sudoers OR - * c) there are args in sudoers and on command line and they match - * else return false. + * If sudoers_cmnd has meta characters in it, we need to + * use glob(3) and/or fnmatch(3) to do the matching. */ -#define GLOB_FLAGS (GLOB_NOSORT | GLOB_MARK | GLOB_BRACE | GLOB_TILDE) - if (glob(sudoers_cmnd, GLOB_FLAGS, NULL, &gl) != 0) { - globfree(&gl); - return(FALSE); - } - /* For each glob match, compare basename, st_dev and st_ino. */ - for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) { - /* If it ends in '/' it is a directory spec. */ - dlen = strlen(cp); - if (cp[dlen - 1] == '/') { - if (command_matches_dir(cp, dlen)) - return(TRUE); - continue; - } + if (def_fast_glob) + return(command_matches_fnmatch(sudoers_cmnd, sudoers_args)); + return(command_matches_glob(sudoers_cmnd, sudoers_args)); + } + return(command_matches_normal(sudoers_cmnd, sudoers_args)); +} - /* Only proceed if user_base and basename(cp) match */ - if ((base = strrchr(cp, '/')) != NULL) - base++; - else - base = cp; - if (strcmp(user_base, base) != 0 || - stat(cp, &sudoers_stat) == -1) - continue; - if (user_stat == NULL || - (user_stat->st_dev == sudoers_stat.st_dev && - user_stat->st_ino == sudoers_stat.st_ino)) { - efree(safe_cmnd); - safe_cmnd = estrdup(cp); - break; - } - } - globfree(&gl); - if (cp == NULL) - return(FALSE); +static int +command_matches_fnmatch(sudoers_cmnd, sudoers_args) + char *sudoers_cmnd; + char *sudoers_args; +{ + /* + * Return true if fnmatch(3) succeeds AND + * a) there are no args in sudoers OR + * b) there are no args on command line and none required by sudoers OR + * c) there are args in sudoers and on command line and they match + * else return false. + */ + if (fnmatch(sudoers_cmnd, user_cmnd, FNM_PATHNAME) != 0) + return(FALSE); + if (!sudoers_args || + (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) || + (sudoers_args && + fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) { + if (safe_cmnd) + free(safe_cmnd); + safe_cmnd = estrdup(user_cmnd); + return(TRUE); + } else + return(FALSE); +} - if (!sudoers_args || - (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) || - (sudoers_args && - fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) { - efree(safe_cmnd); - safe_cmnd = estrdup(user_cmnd); - return(TRUE); +static int +command_matches_glob(sudoers_cmnd, sudoers_args) + char *sudoers_cmnd; + char *sudoers_args; +{ + struct stat sudoers_stat; + size_t dlen; + char **ap, *base, *cp; + glob_t gl; + + /* + * First check to see if we can avoid the call to glob(3). + * Short circuit if there are no meta chars in the command itself + * and user_base and basename(sudoers_cmnd) don't match. + */ + dlen = strlen(sudoers_cmnd); + if (sudoers_cmnd[dlen - 1] != '/') { + if ((base = strrchr(sudoers_cmnd, '/')) != NULL) { + base++; + if (!has_meta(base) && strcmp(user_base, base) != 0) + return(FALSE); } + } + /* + * Return true if we find a match in the glob(3) results AND + * a) there are no args in sudoers OR + * b) there are no args on command line and none required by sudoers OR + * c) there are args in sudoers and on command line and they match + * else return false. + */ +#define GLOB_FLAGS (GLOB_NOSORT | GLOB_MARK | GLOB_BRACE | GLOB_TILDE) + if (glob(sudoers_cmnd, GLOB_FLAGS, NULL, &gl) != 0) { + globfree(&gl); return(FALSE); - } else { + } + /* For each glob match, compare basename, st_dev and st_ino. */ + for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) { /* If it ends in '/' it is a directory spec. */ - if (sudoers_cmnd[dlen - 1] == '/') - return(command_matches_dir(sudoers_cmnd, dlen)); + dlen = strlen(cp); + if (cp[dlen - 1] == '/') { + if (command_matches_dir(cp, dlen)) + return(TRUE); + continue; + } - /* Only proceed if user_base and basename(sudoers_cmnd) match */ - if ((base = strrchr(sudoers_cmnd, '/')) == NULL) - base = sudoers_cmnd; - else + /* Only proceed if user_base and basename(cp) match */ + if ((base = strrchr(cp, '/')) != NULL) base++; + else + base = cp; if (strcmp(user_base, base) != 0 || - stat(sudoers_cmnd, &sudoers_stat) == -1) - return(FALSE); - - /* - * Return true if inode/device matches AND - * a) there are no args in sudoers OR - * b) there are no args on command line and none req by sudoers OR - * c) there are args in sudoers and on command line and they match - */ - if (user_stat != NULL && - (user_stat->st_dev != sudoers_stat.st_dev || - user_stat->st_ino != sudoers_stat.st_ino)) - return(FALSE); - if (!sudoers_args || - (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) || - (sudoers_args && - fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) { + stat(cp, &sudoers_stat) == -1) + continue; + if (user_stat == NULL || + (user_stat->st_dev == sudoers_stat.st_dev && + user_stat->st_ino == sudoers_stat.st_ino)) { efree(safe_cmnd); - safe_cmnd = estrdup(sudoers_cmnd); - return(TRUE); + safe_cmnd = estrdup(cp); + break; } + } + globfree(&gl); + if (cp == NULL) return(FALSE); + + if (!sudoers_args || + (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) || + (sudoers_args && + fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) { + efree(safe_cmnd); + safe_cmnd = estrdup(user_cmnd); + return(TRUE); } + return(FALSE); +} + +static int +command_matches_normal(sudoers_cmnd, sudoers_args) + char *sudoers_cmnd; + char *sudoers_args; +{ + struct stat sudoers_stat; + char *base; + size_t dlen; + + /* If it ends in '/' it is a directory spec. */ + dlen = strlen(sudoers_cmnd); + if (sudoers_cmnd[dlen - 1] == '/') + return(command_matches_dir(sudoers_cmnd, dlen)); + + /* Only proceed if user_base and basename(sudoers_cmnd) match */ + if ((base = strrchr(sudoers_cmnd, '/')) == NULL) + base = sudoers_cmnd; + else + base++; + if (strcmp(user_base, base) != 0 || + stat(sudoers_cmnd, &sudoers_stat) == -1) + return(FALSE); + + /* + * Return true if inode/device matches AND + * a) there are no args in sudoers OR + * b) there are no args on command line and none req by sudoers OR + * c) there are args in sudoers and on command line and they match + */ + if (user_stat != NULL && + (user_stat->st_dev != sudoers_stat.st_dev || + user_stat->st_ino != sudoers_stat.st_ino)) + return(FALSE); + if (!sudoers_args || + (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) || + (sudoers_args && + fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) { + efree(safe_cmnd); + safe_cmnd = estrdup(sudoers_cmnd); + return(TRUE); + } + return(FALSE); } /* @@ -754,7 +812,6 @@ group_matches(sudoers_group, gr) /* * Returns TRUE if the given user belongs to the named group, * else returns FALSE. - * XXX - reduce the number of group lookups */ int usergr_matches(group, user, pw) @@ -762,7 +819,7 @@ usergr_matches(group, user, pw) char *user; struct passwd *pw; { - struct group *grp; + struct group *grp = NULL; char **cur; int i; @@ -770,14 +827,18 @@ usergr_matches(group, user, pw) if (*group++ != '%') return(FALSE); +#ifdef USING_NONUNIX_GROUPS + if (*group == ':') + return(sudo_nonunix_groupcheck(++group, user, pw)); +#endif /* USING_NONUNIX_GROUPS */ + /* look up user's primary gid in the passwd file */ if (pw == NULL && (pw = sudo_getpwnam(user)) == NULL) - return(FALSE); - - if ((grp = sudo_getgrnam(group)) == NULL) - return(FALSE); + goto try_supplementary; /* check against user's primary (passwd file) gid */ + if ((grp = sudo_getgrnam(group)) == NULL) + goto try_supplementary; if (grp->gr_gid == pw->pw_gid) return(TRUE); @@ -790,12 +851,21 @@ usergr_matches(group, user, pw) if (grp->gr_gid == user_groups[i]) return(TRUE); } - if (grp->gr_mem != NULL) { + +try_supplementary: + if (grp != NULL && grp->gr_mem != NULL) { for (cur = grp->gr_mem; *cur; cur++) if (strcmp(*cur, user) == 0) return(TRUE); } +#ifdef USING_NONUNIX_GROUPS + /* not a Unix group, could be an AD group */ + if (sudo_nonunix_groupcheck_available() && + sudo_nonunix_groupcheck(group, user, pw)) + return(TRUE); +#endif /* USING_NONUNIX_GROUPS */ + return(FALSE); } diff --git a/nonunix.h b/nonunix.h new file mode 100644 index 0000000..09de9d2 --- /dev/null +++ b/nonunix.h @@ -0,0 +1,46 @@ +/* + * (c) 2006 Quest Software, 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: + * + * 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 Quest Software, 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 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. + */ + +#ifndef _NONUNIX_H +#define _NONUNIX_H + +void +sudo_nonunix_groupcheck_init(void); + +void +sudo_nonunix_groupcheck_cleanup(void); + +int +sudo_nonunix_groupcheck( const char* group, const char* user, const struct passwd* pwd ); + +int +sudo_nonunix_groupcheck_available(void); + +#endif /* _NONUNIX_H */ diff --git a/parse.c b/parse.c index ef4a495..eeb0511 100644 --- a/parse.c +++ b/parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005, 2007-2008 Todd C. Miller + * Copyright (c) 2004-2005, 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -49,7 +49,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: parse.c,v 1.238 2008/12/09 13:49:55 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: parse.c,v 1.242 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ /* Characters that must be quoted in sudoers */ @@ -89,7 +89,7 @@ sudo_file_open(nss) { if (def_ignore_local_sudoers) return(-1); - nss->handle = open_sudoers(_PATH_SUDOERS, NULL); + nss->handle = open_sudoers(_PATH_SUDOERS, FALSE, NULL); return(nss->handle ? 0 : -1); } @@ -328,8 +328,10 @@ sudo_file_display_priv_short(pw, us, lbuf) print_member(lbuf, m->name, m->type, m->negated, RUNASALIAS); } - } else { + } else if (tq_empty(&cs->runasgrouplist)) { lbuf_append(lbuf, def_runas_default, NULL); + } else { + lbuf_append(lbuf, pw->pw_name, NULL); } if (!tq_empty(&cs->runasgrouplist)) { lbuf_append(lbuf, " : ", NULL); @@ -377,8 +379,10 @@ sudo_file_display_priv_long(pw, us, lbuf) print_member(lbuf, m->name, m->type, m->negated, RUNASALIAS); } - } else { + } else if (tq_empty(&cs->runasgrouplist)) { lbuf_append(lbuf, def_runas_default, NULL); + } else { + lbuf_append(lbuf, pw->pw_name, NULL); } lbuf_print(lbuf); if (!tq_empty(&cs->runasgrouplist)) { @@ -639,7 +643,7 @@ _print_member(lbuf, name, type, negated, alias_type) } break; case ALIAS: - if ((a = find_alias(name, alias_type)) != NULL) { + if ((a = alias_find(name, alias_type)) != NULL) { tq_foreach_fwd(&a->members, m) { if (m != tq_first(&a->members)) lbuf_append(lbuf, ", ", NULL); diff --git a/parse.h b/parse.h index 1638858..991856f 100644 --- a/parse.h +++ b/parse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2000, 2004, 2007-2008 + * Copyright (c) 1996, 1998-2000, 2004, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Sudo: parse.h,v 1.44 2008/11/09 14:13:12 millert Exp $ + * $Sudo: parse.h,v 1.49 2009/05/25 12:02:41 millert Exp $ */ #ifndef _SUDO_PARSE_H @@ -168,7 +168,6 @@ extern unsigned int alias_seqno; */ char *alias_add __P((char *, int, struct member *)); int addr_matches __P((char *)); -int alias_remove __P((char *, int)); int cmnd_matches __P((struct member *)); int cmndlist_matches __P((struct member_list *)); int command_matches __P((char *, char *)); @@ -181,9 +180,13 @@ int userlist_matches __P((struct passwd *, struct member_list *)); int usergr_matches __P((char *, char *, struct passwd *)); int userpw_matches __P((char *, char *, struct passwd *)); int group_matches __P((char *, struct group *)); -struct alias *find_alias __P((char *, int)); +struct alias *alias_find __P((char *, int)); +struct alias *alias_remove __P((char *, int)); +void alias_free __P((void *)); void alias_apply __P((int (*)(void *, void *), void *)); void init_aliases __P((void)); +void init_lexer __P((void)); void init_parser __P((char *, int)); +int alias_compare __P((const void *, const void *)); #endif /* _SUDO_PARSE_H */ diff --git a/pathnames.h.in b/pathnames.h.in index 430f96a..be46f90 100644 --- a/pathnames.h.in +++ b/pathnames.h.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998, 1999, 2001, 2004 + * Copyright (c) 1996, 1998, 1999, 2001, 2004, 2005, 2007-2009 * Todd C. Miller . * * Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: pathnames.h.in,v 1.63 2008/11/10 13:07:38 millert Exp $ + * $Sudo: pathnames.h.in,v 1.65 2009/05/25 12:02:41 millert Exp $ */ /* @@ -127,3 +127,7 @@ #ifndef _PATH_NSSWITCH_CONF #undef _PATH_NSSWITCH_CONF #endif /* _PATH_NSSWITCH_CONF */ + +#ifndef _PATH_NETSVC_CONF +#undef _PATH_NETSVC_CONF +#endif /* _PATH_NETSVC_CONF */ diff --git a/pwutil.c b/pwutil.c index 2fd0988..bbc3174 100644 --- a/pwutil.c +++ b/pwutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -53,7 +53,7 @@ #include "redblack.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: pwutil.c,v 1.21 2008/11/09 14:13:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: pwutil.c,v 1.23 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ #ifdef MYPW @@ -207,18 +207,16 @@ sudo_getpwuid(uid) if (pw->pw_passwd != NULL) zero_bytes(pw->pw_passwd, strlen(pw->pw_passwd)); pw->pw_passwd = cp; - - if (rbinsert(pwcache_byname, (void *) pw) != NULL) - errorx(1, "unable to cache user name, already exists"); if (rbinsert(pwcache_byuid, (void *) pw) != NULL) - errorx(1, "unable to cache uid, already exists"); + errorx(1, "unable to cache uid %lu (%s), already exists", + uid, pw->pw_name); return(pw); } else { pw = emalloc(sizeof(*pw)); zero_bytes(pw, sizeof(*pw)); pw->pw_uid = uid; if (rbinsert(pwcache_byuid, (void *) pw) != NULL) - errorx(1, "unable to cache uid, already exists"); + errorx(1, "unable to cache uid %lu, already exists", uid); return(NULL); } } @@ -250,11 +248,8 @@ sudo_getpwnam(name) if (pw->pw_passwd != NULL) zero_bytes(pw->pw_passwd, strlen(pw->pw_passwd)); pw->pw_passwd = cp; - if (rbinsert(pwcache_byname, (void *) pw) != NULL) - errorx(1, "unable to cache user name, already exists"); - if (rbinsert(pwcache_byuid, (void *) pw) != NULL) - errorx(1, "unable to cache uid, already exists"); + errorx(1, "unable to cache user %s, already exists", name); return(pw); } else { len = strlen(name) + 1; @@ -266,7 +261,7 @@ sudo_getpwnam(name) pw->pw_name = cp; pw->pw_uid = (uid_t) -1; if (rbinsert(pwcache_byname, (void *) pw) != NULL) - errorx(1, "unable to cache user name, already exists"); + errorx(1, "unable to cache user %s, already exists", name); return(NULL); } } @@ -487,17 +482,16 @@ sudo_getgrgid(gid) */ if ((gr = getgrgid(gid)) != NULL) { gr = sudo_grdup(gr); - if (rbinsert(grcache_byname, (void *) gr) != NULL) - errorx(1, "unable to cache group name, already exists"); if (rbinsert(grcache_bygid, (void *) gr) != NULL) - errorx(1, "unable to cache gid, already exists"); + errorx(1, "unable to cache gid %lu (%s), already exists", + gid, gr->gr_name); return(gr); } else { gr = emalloc(sizeof(*gr)); zero_bytes(gr, sizeof(*gr)); gr->gr_gid = gid; if (rbinsert(grcache_bygid, (void *) gr) != NULL) - errorx(1, "unable to cache gid, already exists"); + errorx(1, "unable to cache gid %lu, already exists, gid"); return(NULL); } } @@ -525,9 +519,7 @@ sudo_getgrnam(name) if ((gr = getgrnam(name)) != NULL) { gr = sudo_grdup(gr); if (rbinsert(grcache_byname, (void *) gr) != NULL) - errorx(1, "unable to cache group name, already exists"); - if (rbinsert(grcache_bygid, (void *) gr) != NULL) - errorx(1, "unable to cache gid, already exists"); + errorx(1, "unable to cache group %s, already exists", name); return(gr); } else { len = strlen(name) + 1; @@ -539,7 +531,7 @@ sudo_getgrnam(name) gr->gr_name = cp; gr->gr_gid = (gid_t) -1; if (rbinsert(grcache_byname, (void *) gr) != NULL) - errorx(1, "unable to cache group name, already exists"); + errorx(1, "unable to cache group %s, already exists", name); return(NULL); } } diff --git a/redblack.c b/redblack.c index 555e938..ac8ea2d 100644 --- a/redblack.c +++ b/redblack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005, 2007 Todd C. Miller + * Copyright (c) 2004-2005, 2007,2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -58,7 +58,7 @@ #include "redblack.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: redblack.c,v 1.10 2008/11/22 15:01:25 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: redblack.c,v 1.12 2009/06/29 13:36:20 millert Exp $"; #endif /* lint */ static void rbrepair __P((struct rbtree *, struct rbnode *)); @@ -77,10 +77,11 @@ static void _rbdestroy __P((struct rbtree *, struct rbnode *, * In addition to the ordinary requirements imposed on binary search * trees, we make the following additional requirements of any valid * red-black tree: - * 1) The root is black. - * 2) All leaves are black. - * 3) Both children of each red node are black. - * 4) The paths from each leaf up to the root each contain the same + * 1) Every node is either red or black. + * 2) The root is black. + * 3) All leaves are black. + * 4) Both children of each red node are black. + * 5) The paths from each leaf up to the root each contain the same * number of black nodes. */ @@ -372,8 +373,8 @@ rbdestroy(tree, destroy) * Delete node 'z' from the tree and return its data pointer. */ void *rbdelete(tree, z) - struct rbtree* tree; - struct rbnode* z; + struct rbtree *tree; + struct rbnode *z; { struct rbnode *x, *y; void *data = z->data; @@ -421,7 +422,7 @@ rbrepair(tree, node) { struct rbnode *sibling; - while (node->color == black) { + while (node->color == black && node != rbroot(tree)) { if (node == node->parent->left) { sibling = node->parent->right; if (sibling->color == red) { @@ -444,7 +445,7 @@ rbrepair(tree, node) node->parent->color = black; sibling->right->color = black; rotate_left(tree, node->parent); - break; + node = rbroot(tree); /* exit loop */ } } else { /* if (node == node->parent->right) */ sibling = node->parent->left; @@ -468,8 +469,9 @@ rbrepair(tree, node) node->parent->color = black; sibling->left->color = black; rotate_right(tree, node->parent); - break; + node = rbroot(tree); /* exit loop */ } } } + node->color = black; } diff --git a/set_perms.c b/set_perms.c index bc88a84..4417330 100644 --- a/set_perms.c +++ b/set_perms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996,1998-2008 Todd C. Miller + * Copyright (c) 1994-1996,1998-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -52,7 +52,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.44 2008/03/06 17:19:56 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.49 2009/06/25 12:44:33 millert Exp $"; #endif /* lint */ #ifdef __TANDEM @@ -77,14 +77,18 @@ static int current_perm = -1; * We only flip the effective gid since it only changes for PERM_SUDOERS. * This version of set_perms() works fine with the "stay_setuid" option. */ -void +int set_perms(perm) int perm; { const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); if (perm == current_perm) - return; + return(1); switch (perm) { case PERM_ROOT: @@ -169,10 +173,13 @@ set_perms(perm) } current_perm = perm; - return; + return(1); bad: - errorx(1, "%s: %s", errstr, + warningx("%s: %s", errstr, errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return(0); + exit(1); } #else @@ -184,14 +191,18 @@ bad: * we are headed for an exec(). * This version of set_perms() works fine with the "stay_setuid" option. */ -void +int set_perms(perm) int perm; { const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); if (perm == current_perm) - return; + return(1); switch (perm) { case PERM_ROOT: @@ -279,10 +290,13 @@ set_perms(perm) } current_perm = perm; - return; + return(1); bad: - errorx(1, "%s: %s", errstr, + warningx("%s: %s", errstr, errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return(0); + exit(1); } # else /* !HAVE_SETRESUID && !HAVE_SETREUID */ @@ -292,14 +306,18 @@ bad: * Set real and effective uids and gids based on perm. * NOTE: does not support the "stay_setuid" option. */ -void +int set_perms(perm) int perm; { const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); if (perm == current_perm) - return; + return(1); /* * Since we only have setuid() and seteuid() and semantics @@ -391,10 +409,13 @@ set_perms(perm) } current_perm = perm; - return; + return(1); bad: - errorx(1, "%s: %s", errstr, + warningx("%s: %s", errstr, errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return(0); + exit(1); } # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */ @@ -404,14 +425,18 @@ bad: * NOTE: does not support the "stay_setuid" or timestampowner options. * Also, SUDOERS_UID and SUDOERS_GID are not used. */ -void +int set_perms(perm) int perm; { const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); if (perm == current_perm) - return; + return(1); switch (perm) { case PERM_ROOT: @@ -448,10 +473,13 @@ set_perms(perm) } current_perm = perm; - return; + return(1); bad: - errorx(1, "%s: %s", errstr, + warningx("%s: %s", errstr, errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return(0); + exit(1); } # endif /* HAVE_SETEUID */ # endif /* HAVE_SETREUID */ @@ -462,7 +490,9 @@ static void runas_setgroups() { static int ngroups = -1; +#ifdef HAVE_GETGROUPS static GETGROUPS_T *groups; +#endif struct passwd *pw; if (def_preserve_groups) @@ -475,14 +505,16 @@ runas_setgroups() pw = runas_pw ? runas_pw : sudo_user.pw; if (initgroups(pw->pw_name, pw->pw_gid) < 0) log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); - if ((ngroups = getgroups(0, NULL)) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't get runas ngroups"); - groups = emalloc2(ngroups, sizeof(GETGROUPS_T)); - if (getgroups(ngroups, groups) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector"); +#ifdef HAVE_GETGROUPS + if ((ngroups = getgroups(0, NULL)) > 0) { + groups = emalloc2(ngroups, sizeof(GETGROUPS_T)); + if (getgroups(ngroups, groups) < 0) + log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector"); + } } else { if (setgroups(ngroups, groups) < 0) log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); +#endif /* HAVE_GETGROUPS */ } } @@ -530,13 +562,9 @@ runas_setup() #ifdef HAVE_LOGIN_CAP_H if (def_use_loginclass) { /* - * We only use setusercontext() set the nice value and rlimits. + * We only use setusercontext() to set the nice value and rlimits. */ flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; - if (!def_preserve_groups) - SET(flags, LOGIN_SETGROUP); - else if (setgid(gid)) - warning("cannot set gid to runas gid"); if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) { if (runas_pw->pw_uid != ROOT_UID) error(1, "unable to set user context"); @@ -545,11 +573,15 @@ runas_setup() } } #endif /* HAVE_LOGIN_CAP_H */ - if (setgid(gid)) - warning("cannot set gid to runas gid"); /* * Initialize group vector */ runas_setgroups(); +#ifdef HAVE_SETEUID + if (setegid(gid)) + warning("cannot set egid to runas gid"); +#endif + if (setgid(gid)) + warning("cannot set gid to runas gid"); } } diff --git a/sudo.c b/sudo.c index 7191ee1..66a1121 100644 --- a/sudo.c +++ b/sudo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996, 1998-2008 Todd C. Miller + * Copyright (c) 1993-1996, 1998-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -95,14 +95,17 @@ # include #endif +#include #include "sudo.h" -#include "sudo_usage.h" #include "lbuf.h" #include "interfaces.h" -#include "version.h" + +#ifdef USING_NONUNIX_GROUPS +# include "nonunix.h" +#endif #ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo.c,v 1.500 2008/11/18 15:57:09 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo.c,v 1.517 2009/05/27 00:49:07 millert Exp $"; #endif /* lint */ /* @@ -231,7 +234,7 @@ main(argc, argv, envp) user_cmnd = "shell"; else if (ISSET(sudo_mode, MODE_EDIT)) user_cmnd = "sudoedit"; - else + else { switch (sudo_mode) { case MODE_VERSION: show_version(); @@ -240,6 +243,7 @@ main(argc, argv, envp) usage(0); break; case MODE_VALIDATE: + case MODE_VALIDATE|MODE_INVALIDATE: user_cmnd = "validate"; pwflag = I_VERIFYPW; break; @@ -253,13 +257,16 @@ main(argc, argv, envp) exit(0); break; case MODE_LIST: + case MODE_LIST|MODE_INVALIDATE: user_cmnd = "list"; pwflag = I_LISTPW; break; case MODE_CHECK: + case MODE_CHECK|MODE_INVALIDATE: pwflag = I_LISTPW; break; } + } /* Must have a command to run... */ if (user_cmnd == NULL && NewArgc == 0) @@ -267,6 +274,10 @@ main(argc, argv, envp) init_vars(sudo_mode, envp); /* XXX - move this later? */ +#ifdef USING_NONUNIX_GROUPS + sudo_nonunix_groupcheck_init(); /* initialise nonunix groups impl */ +#endif /* USING_NONUNIX_GROUPS */ + /* Parse nsswitch.conf for sudoers order. */ snl = sudo_read_nss(); @@ -341,10 +352,22 @@ main(argc, argv, envp) tq_foreach_fwd(snl, nss) { validated = nss->lookup(nss, validated, pwflag); - /* Handle [NOTFOUND=return] */ - if (!ISSET(validated, VALIDATE_OK) && nss->ret_notfound) - break; + if (ISSET(validated, VALIDATE_OK)) { + /* Handle "= auth" in netsvc.conf */ + if (nss->ret_if_found) + break; + } else { + /* Handle [NOTFOUND=return] */ + if (nss->ret_if_notfound) + break; + } } + +#ifdef USING_NONUNIX_GROUPS + /* Finished with the groupcheck code */ + sudo_nonunix_groupcheck_cleanup(); +#endif + if (safe_cmnd == NULL) safe_cmnd = estrdup(user_cmnd); @@ -382,9 +405,10 @@ main(argc, argv, envp) /* Bail if a tty is required and we don't have one. */ if (def_requiretty) { - if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) + if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) { + audit_failure(NewArgv, "no tty"); log_error(NO_MAIL, "sorry, you must have a tty to run sudo"); - else + } else (void) close(fd); } @@ -404,7 +428,7 @@ main(argc, argv, envp) /* Require a password if sudoers says so. */ if (def_authenticate) - check_user(validated, !ISSET(sudo_mode, MODE_NONINTERACTIVE)); + check_user(validated, sudo_mode); /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ /* XXX - causes confusion when root is not listed in sudoers */ @@ -419,10 +443,13 @@ main(argc, argv, envp) if (ISSET(validated, VALIDATE_OK)) { /* Finally tell the user if the command did not exist. */ - if (cmnd_status == NOT_FOUND_DOT) + if (cmnd_status == NOT_FOUND_DOT) { + audit_failure(NewArgv, "command in current directory"); errorx(1, "ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); - else if (cmnd_status == NOT_FOUND) + } else if (cmnd_status == NOT_FOUND) { + audit_failure(NewArgv, "%s: command not found", user_cmnd); errorx(1, "%s: command not found", user_cmnd); + } /* If user specified env vars make sure sudoers allows it. */ if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { @@ -434,9 +461,9 @@ main(argc, argv, envp) } log_allowed(validated); - if (sudo_mode == MODE_CHECK) + if (ISSET(sudo_mode, MODE_CHECK)) rc = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); - else if (sudo_mode == MODE_LIST) + else if (ISSET(sudo_mode, MODE_LIST)) display_privs(snl, list_pw ? list_pw : sudo_user.pw); /* Cleanup sudoers sources */ @@ -444,19 +471,23 @@ main(argc, argv, envp) nss->close(nss); /* Deferred exit due to sudo_ldap_close() */ - if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK || - sudo_mode == MODE_LIST) + if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) exit(rc); /* - * Override user's umask if configured to do so. - * If user's umask is more restrictive, OR in those bits too. + * Set umask based on sudoers. + * If user's umask is more restrictive, OR in those bits too + * unless umask_override is set. */ if (def_umask != 0777) { - mode_t mask = umask(def_umask); - mask |= def_umask; - if (mask != def_umask) - umask(mask); + if (def_umask_override) { + umask(def_umask); + } else { + mode_t mask = umask(def_umask); + mask |= def_umask; + if (mask != def_umask) + umask(mask); + } } /* Restore coredumpsize resource limit. */ @@ -464,6 +495,9 @@ main(argc, argv, envp) (void) setrlimit(RLIMIT_CORE, &corelimit); #endif /* RLIMIT_CORE && !SUDO_DEVEL */ + /* Must audit before uid change. */ + audit_success(NewArgv); + /* Become specified user or root if executing a command. */ if (ISSET(sudo_mode, MODE_RUN)) set_perms(PERM_FULL_RUNAS); @@ -509,9 +543,10 @@ main(argc, argv, envp) closefrom(def_closefrom + 1); #ifndef PROFILING - if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) + if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) { + syslog(LOG_AUTH|LOG_ERR, "fork"); exit(0); - else { + } else { #ifdef HAVE_SELINUX if (is_selinux_enabled() > 0 && user_role != NULL) selinux_exec(user_role, user_type, NewArgv, @@ -530,9 +565,11 @@ main(argc, argv, envp) NewArgv[0] = "sh"; NewArgv[1] = safe_cmnd; execv(_PATH_BSHELL, NewArgv); - } warning("unable to execute %s", safe_cmnd); + } + warning("unable to execute %s", safe_cmnd); exit(127); } else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { + audit_failure(NewArgv, "No user or host"); log_denial(validated, 1); exit(1); } else { @@ -554,6 +591,7 @@ main(argc, argv, envp) /* Just tell the user they are not allowed to run foo. */ log_denial(validated, 1); } + audit_failure(NewArgv, "validation failure"); exit(1); } exit(0); /* not reached */ @@ -666,7 +704,7 @@ init_vars(sudo_mode, envp) * users to place "sudo -k" in a .logout file which can cause sudo to * be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died. */ - if (sudo_mode & (MODE_INVALIDATE|MODE_KILL)) + if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) errorx(1, "unknown uid: %s", pw_name); log_error(0, "unknown uid: %s", pw_name); } @@ -802,6 +840,9 @@ set_cmnd(sudo_mode) if (!update_defaults(SETDEF_CMND)) log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); + if (!runas_user && !runas_group) + set_runaspw(def_runas_default); /* may have been updated above */ + return(rval); } @@ -817,7 +858,7 @@ parse_args(argc, argv) { int mode = 0; /* what mode is sudo to be run in? */ int flags = 0; /* mode flags */ - int ch; + int valid_flags, ch; /* First, check to see if we were invoked as "sudoedit". */ if (strcmp(getprogname(), "sudoedit") == 0) @@ -831,6 +872,10 @@ parse_args(argc, argv) #define is_envar (optind < argc && argv[optind][0] != '/' && \ strchr(argv[optind], '=') != NULL) + /* Flags allowed when running a command */ + valid_flags = MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME| + MODE_LOGIN_SHELL|MODE_INVALIDATE|MODE_NONINTERACTIVE| + MODE_PRESERVE_GROUPS|MODE_SHELL; for (;;) { /* * We disable arg permutation for GNU getopt(). @@ -869,6 +914,7 @@ parse_args(argc, argv) if (mode && mode != MODE_EDIT) usage_excl(1); mode = MODE_EDIT; + valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; break; case 'g': runas_group = optarg; @@ -877,28 +923,31 @@ parse_args(argc, argv) SET(flags, MODE_RESET_HOME); break; case 'h': - if (mode && mode != MODE_HELP) - usage_excl(1); + if (mode && mode != MODE_HELP) { + if (strcmp(getprogname(), "sudoedit") != 0) + usage_excl(1); + } mode = MODE_HELP; + valid_flags = 0; break; case 'i': SET(flags, MODE_LOGIN_SHELL); def_env_reset = TRUE; break; case 'k': - if (mode && mode != MODE_INVALIDATE) - usage_excl(1); - mode = MODE_INVALIDATE; + SET(flags, MODE_INVALIDATE); break; case 'K': if (mode && mode != MODE_KILL) usage_excl(1); mode = MODE_KILL; + valid_flags = 0; break; case 'L': if (mode && mode != MODE_LISTDEFS) usage_excl(1); mode = MODE_LISTDEFS; + valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; break; case 'l': if (mode) { @@ -908,6 +957,7 @@ parse_args(argc, argv) usage_excl(1); } mode = MODE_LIST; + valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; break; case 'n': SET(flags, MODE_NONINTERACTIVE); @@ -944,11 +994,13 @@ parse_args(argc, argv) if (mode && mode != MODE_VALIDATE) usage_excl(1); mode = MODE_VALIDATE; + valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; break; case 'V': if (mode && mode != MODE_VERSION) usage_excl(1); mode = MODE_VERSION; + valid_flags = 0; break; default: usage(1); @@ -973,8 +1025,16 @@ parse_args(argc, argv) NewArgc = argc - optind; NewArgv = argv + optind; - if (!mode) - mode = MODE_RUN; + if (!mode) { + /* Defer -k mode setting until we know whether it is a flag or not */ + if (ISSET(flags, MODE_INVALIDATE) && NewArgc == 0) { + mode = MODE_INVALIDATE; /* -k by itself */ + CLR(flags, MODE_INVALIDATE); + valid_flags = 0; + } else { + mode = MODE_RUN; /* running a command */ + } + } if (NewArgc > 0 && mode == MODE_LIST) mode = MODE_CHECK; @@ -990,6 +1050,8 @@ parse_args(argc, argv) } SET(flags, MODE_SHELL); } + if ((flags & valid_flags) != flags) + usage(1); if (mode == MODE_EDIT && (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) { if (ISSET(mode, MODE_PRESERVE_ENV)) @@ -1024,8 +1086,9 @@ parse_args(argc, argv) * Returns a handle to the sudoers file or NULL on error. */ FILE * -open_sudoers(sudoers, keepopen) +open_sudoers(sudoers, doedit, keepopen) const char *sudoers; + int doedit; int *keepopen; { struct stat statbuf; @@ -1077,16 +1140,18 @@ open_sudoers(sudoers, keepopen) (unsigned long) statbuf.st_gid, (unsigned long) SUDOERS_GID); else if ((fp = fopen(sudoers, "r")) == NULL) log_error(USE_ERRNO, "can't open %s", sudoers); - else if (statbuf.st_size != 0) { + else { /* * Make sure we can actually read sudoers so we can present the - * user with a reasonable error message. + * user with a reasonable error message (unlike the lexer). */ - if (fgetc(fp) == EOF) - log_error(USE_ERRNO, "can't read %s", sudoers); - rewind(fp); + if (statbuf.st_size != 0) { + if (fgetc(fp) == EOF) + log_error(USE_ERRNO, "can't read %s", sudoers); + rewind(fp); + } + (void) fcntl(fileno(fp), F_SETFD, 1); } - (void) fcntl(fileno(fp), F_SETFD, 1); set_perms(PERM_ROOT); /* change back to root */ return(fp); @@ -1313,8 +1378,10 @@ set_runaspw(user) if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); } else { - if ((runas_pw = sudo_getpwnam(user)) == NULL) + if ((runas_pw = sudo_getpwnam(user)) == NULL) { + audit_failure(NewArgv, "unknown user: %s", user); log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user); + } } } @@ -1384,7 +1451,7 @@ cleanup(gotsignal) static void show_version() { - (void) printf("Sudo version %s\n", version); + (void) printf("Sudo version %s\n", PACKAGE_VERSION); if (getuid() == 0) { putchar('\n'); (void) printf("Sudoers path: %s\n", _PATH_SUDOERS); @@ -1409,7 +1476,7 @@ static void usage_excl(exit_val) int exit_val; { - warningx("Only one of the -e, -h, -i, -k, -K, -l, -s, -v or -V options may be specified"); + warningx("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"); usage(exit_val); } @@ -1422,21 +1489,22 @@ usage(exit_val) int exit_val; { struct lbuf lbuf; - char *uvec[5]; + char *uvec[6]; int i, ulen; /* * Use usage vectors appropriate to the progname. */ if (strcmp(getprogname(), "sudoedit") == 0) { - uvec[0] = SUDO_USAGE4 + 3; + uvec[0] = SUDO_USAGE5 + 3; uvec[1] = NULL; } else { uvec[0] = SUDO_USAGE1; uvec[1] = SUDO_USAGE2; uvec[2] = SUDO_USAGE3; uvec[3] = SUDO_USAGE4; - uvec[4] = NULL; + uvec[4] = SUDO_USAGE5; + uvec[5] = NULL; } /* diff --git a/sudo.cat b/sudo.cat index 07290ee..c737547 100644 --- a/sudo.cat +++ b/sudo.cat @@ -8,10 +8,12 @@ NNAAMMEE sudo, sudoedit - execute a command as another user SSYYNNOOPPSSIISS - ssuuddoo [--nn] --hh | --KK | --kk | --LL | --VV | --vv + ssuuddoo --hh | --KK | --kk | --LL | --VV - ssuuddoo --ll[[ll]] [--AAnnSS] [--gg _g_r_o_u_p_n_a_m_e|_#_g_i_d] [--UU _u_s_e_r_n_a_m_e] [--uu _u_s_e_r_n_a_m_e|_#_u_i_d] - [_c_o_m_m_a_n_d] + ssuuddoo --vv [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--pp _p_r_o_m_p_t] + + ssuuddoo --ll[[ll]] [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--gg _g_r_o_u_p_n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] + [--UU _u_s_e_r_n_a_m_e] [--uu _u_s_e_r_n_a_m_e|_#_u_i_d] [_c_o_m_m_a_n_d] ssuuddoo [--AAbbEEHHnnPPSS] [--aa _a_u_t_h___t_y_p_e] [--CC _f_d] [--cc _c_l_a_s_s|_-] [--gg _g_r_o_u_p_n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] [--uu _u_s_e_r_n_a_m_e|_#_u_i_d] [VVAARR=_v_a_l_u_e] [--ii | --ss] [_c_o_m_m_a_n_d] @@ -56,12 +58,10 @@ DDEESSCCRRIIPPTTIIOONN the sudoers lookup is still done for root, not the user specified by SUDO_USER. - ssuuddoo can log both successful and unsuccessful attempts (as well as - errors) to _s_y_s_l_o_g(3), a log file, or both. By default ssuuddoo will log -1.7.0 November 15, 2008 1 +1.7.2 June 15, 2009 1 @@ -70,6 +70,8 @@ DDEESSCCRRIIPPTTIIOONN SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + ssuuddoo can log both successful and unsuccessful attempts (as well as + errors) to _s_y_s_l_o_g(3), a log file, or both. By default ssuuddoo will log via _s_y_s_l_o_g(3) but this is changeable at configure time or via the _s_u_d_o_e_r_s file. @@ -78,12 +80,12 @@ OOPPTTIIOONNSS -A Normally, if ssuuddoo requires a password, it will read it from the current terminal. If the --AA (_a_s_k_p_a_s_s) option is - specified, a helper program is executed to read the user's - password and output the password to the standard output. - If the SUDO_ASKPASS environment variable is set, it - specifies the path to the helper program. Otherwise, the - value specified by the _a_s_k_p_a_s_s option in _s_u_d_o_e_r_s(4) is - used. + specified, a (possibly graphical) helper program is + executed to read the user's password and output the + password to the standard output. If the SUDO_ASKPASS + environment variable is set, it specifies the path to the + helper program. Otherwise, the value specified by the + _a_s_k_p_a_s_s option in _s_u_d_o_e_r_s(4) is used. -a _t_y_p_e The --aa (_a_u_t_h_e_n_t_i_c_a_t_i_o_n _t_y_p_e) option causes ssuuddoo to use the specified authentication type when validating the user, as @@ -123,11 +125,9 @@ OOPPTTIIOONNSS either the matching command has the SETENV tag or the _s_e_t_e_n_v option is set in _s_u_d_o_e_r_s(4). - -e The --ee (_e_d_i_t) option indicates that, instead of running a - -1.7.0 November 15, 2008 2 +1.7.2 June 15, 2009 2 @@ -136,6 +136,7 @@ OOPPTTIIOONNSS SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + -e The --ee (_e_d_i_t) option indicates that, instead of running a command, the user wishes to edit one or more files. In lieu of a command, the string "sudoedit" is used when consulting the _s_u_d_o_e_r_s file. If the user is authorized by @@ -189,11 +190,10 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) execution. Otherwise, an interactive shell is executed. ssuuddoo attempts to change to that user's home directory before running the shell. It also initializes the - environment, leaving _D_I_S_P_L_A_Y and _T_E_R_M unchanged, setting -1.7.0 November 15, 2008 3 +1.7.2 June 15, 2009 3 @@ -202,19 +202,28 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + environment, leaving _D_I_S_P_L_A_Y and _T_E_R_M unchanged, setting _H_O_M_E, _S_H_E_L_L, _U_S_E_R, _L_O_G_N_A_M_E, and _P_A_T_H, as well as the contents of _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t on Linux and AIX systems. All other environment variables are removed. -K The --KK (sure _k_i_l_l) option is like --kk except that it removes - the user's timestamp entirely. Like --kk, this option does - not require a password. - - -k The --kk (_k_i_l_l) option to ssuuddoo invalidates the user's - timestamp by setting the time on it to the Epoch. The next - time ssuuddoo is run a password will be required. This option - does not require a password and was added to allow a user - to revoke ssuuddoo permissions from a .logout file. + the user's timestamp entirely and may not be used in + conjunction with a command or other option. This option + does not require a password. + + -k When used by itself, the --kk (_k_i_l_l) option to ssuuddoo + invalidates the user's timestamp by setting the time on it + to the Epoch. The next time ssuuddoo is run a password will be + required. This option does not require a password and was + added to allow a user to revoke ssuuddoo permissions from a + .logout file. + + When used in conjunction with a command or an option that + may require a password, the --kk option will cause ssuuddoo to + ignore the user's timestamp file. As a result, ssuuddoo will + prompt for a password (if one is required by _s_u_d_o_e_r_s) and + will not update the user's timestamp file. -L The --LL (_l_i_s_t defaults) option will list out the parameters that may be set in a _D_e_f_a_u_l_t_s line along with a short @@ -248,26 +257,25 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) password prompt and use a custom one. The following percent (`%') escapes are supported: - %H expanded to the local hostname including the domain - name (on if the machine's hostname is fully qualified - or the _f_q_d_n _s_u_d_o_e_r_s option is set) - - %h expanded to the local hostname without the domain name - %p expanded to the user whose password is being asked for - (respects the _r_o_o_t_p_w, _t_a_r_g_e_t_p_w and _r_u_n_a_s_p_w flags in +1.7.2 June 15, 2009 4 -1.7.0 November 15, 2008 4 +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + %H expanded to the local hostname including the domain + name (on if the machine's hostname is fully qualified + or the _f_q_d_n _s_u_d_o_e_r_s option is set) + %h expanded to the local hostname without the domain name + %p expanded to the user whose password is being asked for + (respects the _r_o_o_t_p_w, _t_a_r_g_e_t_p_w and _r_u_n_a_s_p_w flags in _s_u_d_o_e_r_s) %U expanded to the login name of the user the command will @@ -314,26 +322,26 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -v If given the --vv (_v_a_l_i_d_a_t_e) option, ssuuddoo will update the user's timestamp, prompting for the user's password if necessary. This extends the ssuuddoo timeout for another 5 - minutes (or whatever the timeout is set to in _s_u_d_o_e_r_s) but - does not run a command. - -- The ---- option indicates that ssuuddoo should stop processing - command line arguments. It is most useful in conjunction - with the --ss option. - Environment variables to be set for the command may also be passed on +1.7.2 June 15, 2009 5 -1.7.0 November 15, 2008 5 +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + minutes (or whatever the timeout is set to in _s_u_d_o_e_r_s) but + does not run a command. + -- The ---- option indicates that ssuuddoo should stop processing + command line arguments. It is most useful in conjunction + with the --ss option. + Environment variables to be set for the command may also be passed on the command line in the form of VVAARR=_v_a_l_u_e, e.g. LLDD__LLIIBBRRAARRYY__PPAATTHH=_/_u_s_r_/_l_o_c_a_l_/_p_k_g_/_l_i_b. Variables passed on the command line are subject to the same restrictions as normal environment @@ -380,18 +388,10 @@ SSEECCUURRIITTYY NNOOTTEESS output of sudo -V when run as root. Note that the dynamic linker on most operating systems will remove - variables that can control dynamic linking from the environment of - setuid executables, including ssuuddoo. Depending on the operating system - this may include _RLD*, DYLD_*, LD_*, LDR_*, LIBPATH, SHLIB_PATH, and - others. These type of variables are removed from the environment - before ssuuddoo even begins execution and, as such, it is not possible for - ssuuddoo to preserve them. - - To prevent command spoofing, ssuuddoo checks "." and "" (both denoting -1.7.0 November 15, 2008 6 +1.7.2 June 15, 2009 6 @@ -400,6 +400,14 @@ SSEECCUURRIITTYY NNOOTTEESS SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + variables that can control dynamic linking from the environment of + setuid executables, including ssuuddoo. Depending on the operating system + this may include _RLD*, DYLD_*, LD_*, LDR_*, LIBPATH, SHLIB_PATH, and + others. These type of variables are removed from the environment + before ssuuddoo even begins execution and, as such, it is not possible for + ssuuddoo to preserve them. + + To prevent command spoofing, ssuuddoo checks "." and "" (both denoting current directory) last when searching for a command in the user's PATH (if one or both are in the PATH). Note, however, that the actual PATH environment variable is _n_o_t modified and is passed unchanged to the @@ -447,25 +455,24 @@ EENNVVIIRROONNMMEENNTT --enable-shell-sets-home option), set to homedir of the target user - PATH Set to a sane value if the _s_e_c_u_r_e___p_a_t_h sudoers option - is set. - SHELL Used to determine shell to run with -s option - - SUDO_ASKPASS Specifies the path to a helper program used to read the - password if no terminal is available or if the -A +1.7.2 June 15, 2009 7 -1.7.0 November 15, 2008 7 +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + PATH Set to a sane value if the _s_e_c_u_r_e___p_a_t_h sudoers option + is set. + SHELL Used to determine shell to run with -s option + SUDO_ASKPASS Specifies the path to a helper program used to read the + password if no terminal is available or if the -A option is specified. SUDO_COMMAND Set to the command run by sudo @@ -504,33 +511,42 @@ EEXXAAMMPPLLEESS $ sudo ls /usr/local/protected - To list the home directory of user yazza on a machine where the file - system holding ~yazza is not exported as root: + To list the home directory of user yaz on a machine where the file + system holding ~yaz is not exported as root: - $ sudo -u yazza ls ~yazza + $ sudo -u yaz ls ~yaz To edit the _i_n_d_e_x_._h_t_m_l file as user www: $ sudo -u www vi ~www/htdocs/index.html - To shutdown a machine: - $ sudo shutdown -r +15 "quick reboot" - 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 cd and file - redirection work. + +1.7.2 June 15, 2009 8 -1.7.0 November 15, 2008 8 +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + To view system logs only accessible to root and users in the adm group: -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + $ sudo -g adm view /var/log/syslog + To run an editor as jim with a different primary group: + + $ sudo -u jim -g audio vi ~jim/sound.txt + + To shutdown a machine: + + $ sudo shutdown -r +15 "quick reboot" + + 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 cd and file + redirection work. $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" @@ -570,6 +586,18 @@ CCAAVVEEAATTSS make setuid shell scripts unsafe on some operating systems (if your OS has a /dev/fd/ directory, setuid shell scripts are generally safe). + + + +1.7.2 June 15, 2009 9 + + + + + +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + + BBUUGGSS If you feel you have found a bug in ssuuddoo, please submit a bug report at http://www.sudo.ws/sudo/bugs/ @@ -589,6 +617,44 @@ DDIISSCCLLAAIIMMEERR -1.7.0 November 15, 2008 9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1.7.2 June 15, 2009 10 diff --git a/sudo.h b/sudo.h index ac5fdbd..afb4e4e 100644 --- a/sudo.h +++ b/sudo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996, 1998-2005, 2007-2008 + * Copyright (c) 1993-1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: sudo.h,v 1.269 2008/11/25 17:01:34 millert Exp $ + * $Sudo: sudo.h,v 1.273 2009/05/25 12:02:41 millert Exp $ */ #ifndef _SUDO_SUDO_H @@ -129,6 +129,8 @@ struct sudo_user { #define PERM_RUNAS 0x04 #define PERM_FULL_RUNAS 0x05 #define PERM_TIMESTAMP 0x06 +#define PERM_NOEXIT 0x10 /* flag */ +#define PERM_MASK 0xf0 /* * Shortcuts for sudo_user contents. @@ -237,6 +239,12 @@ void *memrchr __P((const void *, int, size_t)); #ifndef HAVE_MKSTEMP int mkstemp __P((char *)); #endif +#ifndef HAVE_SETENV +int setenv __P((const char *, const char *, int)); +#endif +#ifndef HAVE_UNSETENV +int unsetenv __P((const char *)); +#endif char *sudo_goodpath __P((const char *, struct stat *)); char *tgetpass __P((const char *, int, int)); int find_path __P((char *, char **, struct stat *, char *)); @@ -263,7 +271,7 @@ int sudo_file_display_cmnd __P((struct sudo_nss *, struct passwd *)); int sudo_file_display_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); int sudo_file_display_bound_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); int sudo_file_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *)); -void set_perms __P((int)); +int set_perms __P((int)); void remove_timestamp __P((int)); int check_secureware __P((char *)); void sia_attempt_auth __P((void)); @@ -292,13 +300,11 @@ char *sudo_getepw __P((const struct passwd *)); int pam_prep_user __P((struct passwd *)); void zero_bytes __P((volatile void *, size_t)); int gettime __P((struct timespec *)); -FILE *open_sudoers __P((const char *, int *)); +FILE *open_sudoers __P((const char *, int, int *)); void display_privs __P((struct sudo_nss_list *, struct passwd *)); int display_cmnd __P((struct sudo_nss_list *, struct passwd *)); int get_ttycols __P((void)); char *sudo_parseln __P((FILE *)); -void sudo_setenv __P((const char *, const char *, int)); -void sudo_unsetenv __P((const char *)); void sudo_setgrent __P((void)); void sudo_endgrent __P((void)); void sudo_setpwent __P((void)); diff --git a/sudo.man.in b/sudo.man.in index 26d8a30..13c0d6d 100644 --- a/sudo.man.in +++ b/sudo.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994-1996, 1998-2005, 2007-2008 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2009 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.\" $Sudo: sudo.man.in,v 1.53 2008/11/15 18:34:26 millert Exp $ +.\" $Sudo: sudo.man.in,v 1.56 2009/06/29 13:36:42 millert Exp $ .\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: @@ -153,7 +153,7 @@ .\" ======================================================================== .\" .IX Title "SUDO @mansectsu@" -.TH SUDO @mansectsu@ "November 15, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.TH SUDO @mansectsu@ "June 15, 2009" "1.7.2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -162,10 +162,16 @@ sudo, sudoedit \- execute a command as another user .SH "SYNOPSIS" .IX Header "SYNOPSIS" -\&\fBsudo\fR [\fB\-n\fR] \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-L\fR | \fB\-V\fR | \fB\-v\fR +\&\fBsudo\fR \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-L\fR | \fB\-V\fR .PP -\&\fBsudo\fR \fB\-l[l]\fR [\fB\-AnS\fR] [\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-U\fR\ \fIusername\fR] -[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] [\fIcommand\fR] +\&\fBsudo\fR \fB\-v\fR [\fB\-AknS\fR] +@BAMAN@[\fB\-a\fR\ \fIauth_type\fR] +[\fB\-p\fR\ \fIprompt\fR] +.PP +\&\fBsudo\fR \fB\-l[l]\fR [\fB\-AknS\fR] +@BAMAN@[\fB\-a\fR\ \fIauth_type\fR] +[\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] +[\fB\-U\fR\ \fIusername\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] [\fIcommand\fR] .PP \&\fBsudo\fR [\fB\-AbEHnPS\fR] @BAMAN@[\fB\-a\fR\ \fIauth_type\fR] @@ -235,11 +241,11 @@ or via the \fIsudoers\fR file. .IX Item "-A" Normally, if \fBsudo\fR requires a password, it will read it from the current terminal. If the \fB\-A\fR (\fIaskpass\fR) option is specified, -a helper program is executed to read the user's password and output -the password to the standard output. If the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR -environment variable is set, it specifies the path to the helper -program. Otherwise, the value specified by the \fIaskpass\fR option -in \fIsudoers\fR\|(@mansectform@) is used. +a (possibly graphical) helper program is executed to read the +user's password and output the password to the standard output. If +the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR environment variable is set, it specifies the +path to the helper program. Otherwise, the value specified by the +\&\fIaskpass\fR option in \fIsudoers\fR\|(@mansectform@) is used. @BAMAN@.IP "\-a \fItype\fR" 12 @BAMAN@.IX Item "-a type" @BAMAN@The \fB\-a\fR (\fIauthentication type\fR) option causes \fBsudo\fR to use the @@ -344,15 +350,22 @@ All other environment variables are removed. .IP "\-K" 12 .IX Item "-K" The \fB\-K\fR (sure \fIkill\fR) option is like \fB\-k\fR except that it removes -the user's timestamp entirely. Like \fB\-k\fR, this option does not -require a password. +the user's timestamp entirely and may not be used in conjunction +with a command or other option. This option does not require a +password. .IP "\-k" 12 .IX Item "-k" -The \fB\-k\fR (\fIkill\fR) option to \fBsudo\fR invalidates the user's timestamp -by setting the time on it to the Epoch. 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 .logout -file. +When used by itself, the \fB\-k\fR (\fIkill\fR) option to \fBsudo\fR invalidates +the user's timestamp by setting the time on it to the Epoch. 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 .logout file. +.Sp +When used in conjunction with a command or an option that may require +a password, the \fB\-k\fR option will cause \fBsudo\fR to ignore the user's +timestamp file. As a result, \fBsudo\fR will prompt for a password +(if one is required by \fIsudoers\fR) and will not update the user's +timestamp file. .IP "\-L" 12 .IX Item "-L" The \fB\-L\fR (\fIlist\fR defaults) option will list out the parameters @@ -654,11 +667,11 @@ To get a file listing of an unreadable directory: \& $ sudo ls /usr/local/protected .Ve .PP -To list the home directory of user yazza on a machine where the -file system holding ~yazza is not exported as root: +To list the home directory of user yaz on a machine where the +file system holding ~yaz is not exported as root: .PP .Vb 1 -\& $ sudo \-u yazza ls ~yazza +\& $ sudo \-u yaz ls ~yaz .Ve .PP To edit the \fIindex.html\fR file as user www: @@ -667,6 +680,18 @@ To edit the \fIindex.html\fR file as user www: \& $ sudo \-u www vi ~www/htdocs/index.html .Ve .PP +To view system logs only accessible to root and users in the adm group: +.PP +.Vb 1 +\& $ sudo \-g adm view /var/log/syslog +.Ve +.PP +To run an editor as jim with a different primary group: +.PP +.Vb 1 +\& $ sudo \-u jim \-g audio vi ~jim/sound.txt +.Ve +.PP To shutdown a machine: .PP .Vb 1 diff --git a/sudo.pod b/sudo.pod index e96f044..c8b370d 100644 --- a/sudo.pod +++ b/sudo.pod @@ -1,4 +1,4 @@ -Copyright (c) 1994-1996, 1998-2005, 2007-2008 +Copyright (c) 1994-1996, 1998-2005, 2007-2009 Todd C. Miller Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ 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. -$Sudo: sudo.pod,v 1.120 2008/11/15 18:34:01 millert Exp $ +$Sudo: sudo.pod,v 1.124 2009/06/15 21:19:47 millert Exp $ =pod =head1 NAME @@ -27,10 +27,16 @@ sudo, sudoedit - execute a command as another user =head1 SYNOPSIS -B [B<-n>] B<-h> | B<-K> | B<-k> | B<-L> | B<-V> | B<-v> +B B<-h> | B<-K> | B<-k> | B<-L> | B<-V> -B B<-l[l]> [B<-AnS>] S<[B<-g> I|I<#gid>]> S<[B<-U> I]> -S<[B<-u> I|I<#uid>]> [I] +B B<-v> [B<-AknS>] +S<[B<-a> I]> +S<[B<-p> I]> + +B B<-l[l]> [B<-AknS>] +S<[B<-a> I]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-U> I]> S<[B<-u> I|I<#uid>]> [I] B [B<-AbEHnPS>] S<[B<-a> I]> @@ -105,11 +111,11 @@ B accepts the following command line options: Normally, if B requires a password, it will read it from the current terminal. If the B<-A> (I) option is specified, -a helper program is executed to read the user's password and output -the password to the standard output. If the C -environment variable is set, it specifies the path to the helper -program. Otherwise, the value specified by the I option -in L is used. +a (possibly graphical) helper program is executed to read the +user's password and output the password to the standard output. If +the C environment variable is set, it specifies the +path to the helper program. Otherwise, the value specified by the +I option in L is used. =item -a I @@ -231,16 +237,23 @@ All other environment variables are removed. =item -K The B<-K> (sure I) option is like B<-k> except that it removes -the user's timestamp entirely. Like B<-k>, this option does not -require a password. +the user's timestamp entirely and may not be used in conjunction +with a command or other option. This option does not require a +password. =item -k -The B<-k> (I) option to B invalidates the user's timestamp -by setting the time on it to the Epoch. The next time B is -run a password will be required. This option does not require a password -and was added to allow a user to revoke B permissions from a .logout -file. +When used by itself, the B<-k> (I) option to B invalidates +the user's timestamp by setting the time on it to the Epoch. The +next time B is run a password will be required. This option +does not require a password and was added to allow a user to revoke +B permissions from a .logout file. + +When used in conjunction with a command or an option that may require +a password, the B<-k> option will cause B to ignore the user's +timestamp file. As a result, B will prompt for a password +(if one is required by I) and will not update the user's +timestamp file. =item -L @@ -570,15 +583,23 @@ To get a file listing of an unreadable directory: $ sudo ls /usr/local/protected -To list the home directory of user yazza on a machine where the -file system holding ~yazza is not exported as root: +To list the home directory of user yaz on a machine where the +file system holding ~yaz is not exported as root: - $ sudo -u yazza ls ~yazza + $ sudo -u yaz ls ~yaz To edit the F file as user www: $ sudo -u www vi ~www/htdocs/index.html +To view system logs only accessible to root and users in the adm group: + + $ sudo -g adm view /var/log/syslog + +To run an editor as jim with a different primary group: + + $ sudo -u jim -g audio vi ~jim/sound.txt + To shutdown a machine: $ sudo shutdown -r +15 "quick reboot" diff --git a/sudo_nss.c b/sudo_nss.c index 7d70617..138c0e2 100644 --- a/sudo_nss.c +++ b/sudo_nss.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008 Todd C. Miller + * Copyright (c) 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,12 +39,13 @@ #endif /* HAVE_UNISTD_H */ #include #include +#include #include "sudo.h" #include "lbuf.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo_nss.c,v 1.6 2008/02/08 13:18:12 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo_nss.c,v 1.8 2009/05/25 12:02:41 millert Exp $"; #endif /* lint */ extern struct sudo_nss sudo_nss_file; @@ -89,7 +90,7 @@ sudo_read_nss() got_match = TRUE; } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { /* NOTFOUND affects the most recent entry */ - tq_last(&snl)->ret_notfound = TRUE; + tq_last(&snl)->ret_if_notfound = TRUE; got_match = FALSE; } else got_match = FALSE; @@ -109,6 +110,85 @@ nomatch: #else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */ +# if defined(HAVE_LDAP) && defined(_PATH_NETSVC_CONF) + +/* + * Read in /etc/netsvc.conf (like nsswitch.conf on AIX) + * Returns a tail queue of matches. + */ +struct sudo_nss_list * +sudo_read_nss() +{ + FILE *fp; + char *cp, *ep; + int saw_files = FALSE; + int saw_ldap = FALSE; + int got_match = FALSE; + static struct sudo_nss_list snl; + + if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL) + goto nomatch; + + while ((cp = sudo_parseln(fp)) != NULL) { + /* Skip blank or comment lines */ + if (*cp == '\0') + continue; + + /* Look for a line starting with "sudoers = " */ + if (strncasecmp(cp, "sudoers", 7) != 0) + continue; + cp += 7; + while (isspace((unsigned char)*cp)) + cp++; + if (*cp++ != '=') + continue; + + /* Parse line */ + for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) { + /* Trim leading whitespace. */ + while (isspace((unsigned char)*cp)) + cp++; + + if (!saw_files && strncasecmp(cp, "files", 5) == 0 && + (isspace((unsigned char)cp[5]) || cp[5] == '\0')) { + tq_append(&snl, &sudo_nss_file); + got_match = TRUE; + ep = &cp[5]; + } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 && + (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { + tq_append(&snl, &sudo_nss_ldap); + got_match = TRUE; + ep = &cp[4]; + } else { + got_match = FALSE; + } + + /* check for = auth qualifier */ + if (got_match && *ep) { + cp = ep; + while (isspace((unsigned char)*cp) || *cp == '=') + cp++; + if (strncasecmp(cp, "auth", 4) == 0 && + (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { + tq_last(&snl)->ret_if_found = TRUE; + } + } + } + /* Only parse the first "sudoers" line */ + break; + } + fclose(fp); + +nomatch: + /* Default to files only if no matches */ + if (tq_empty(&snl)) + tq_append(&snl, &sudo_nss_file); + + return(&snl); +} + +# else /* !_PATH_NETSVC_CONF && !_PATH_NSSWITCH_CONF */ + /* * Non-nsswitch.conf version with hard-coded order. */ @@ -117,14 +197,16 @@ sudo_read_nss() { static struct sudo_nss_list snl; -# ifdef HAVE_LDAP +# ifdef HAVE_LDAP tq_append(&snl, &sudo_nss_ldap); -# endif +# endif tq_append(&snl, &sudo_nss_file); return(&snl); } +# endif /* !HAVE_LDAP || !_PATH_NETSVC_CONF */ + #endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */ /* Reset user_groups based on passwd entry. */ diff --git a/sudo_nss.h b/sudo_nss.h index 361510f..1822465 100644 --- a/sudo_nss.h +++ b/sudo_nss.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008 Todd C. Miller + * Copyright (c) 2007-2009 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Sudo: sudo_nss.h,v 1.5 2008/11/09 14:13:12 millert Exp $ + * $Sudo: sudo_nss.h,v 1.7 2009/05/25 12:02:42 millert Exp $ */ struct lbuf; @@ -32,7 +32,8 @@ struct sudo_nss { int (*display_bound_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); int (*display_privs) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); void *handle; - int ret_notfound; + short ret_if_found; + short ret_if_notfound; }; TQ_DECLARE(sudo_nss) diff --git a/sudo_usage.h.in b/sudo_usage.h.in index 5a1bfc6..e310b0c 100644 --- a/sudo_usage.h.in +++ b/sudo_usage.h.in @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2007-2009 Todd C. Miller + * + * 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. + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Sudo: sudo_usage.h.in,v 1.10 2009/05/25 12:02:42 millert Exp $ + */ + #ifndef _SUDO_USAGE_H #define _SUDO_USAGE_H @@ -5,9 +25,10 @@ * Usage strings for sudo. These are here because we * need to be able to substitute values from configure. */ -#define SUDO_USAGE1 " [-n] -h | -K | -k | -L | -V | -v" -#define SUDO_USAGE2 " -l[l] [-AnS] [-g groupname|#gid] [-U username] [-u username|#uid] [-g groupname|#gid] [command]" -#define SUDO_USAGE3 " [-AbEHnPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []" -#define SUDO_USAGE4 " -e [-AnS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..." +#define SUDO_USAGE1 " -h | -K | -k | -L | -V" +#define SUDO_USAGE2 " -v [-AknS] @BSDAUTH_USAGE@[-p prompt]" +#define SUDO_USAGE3 " -l[l] [-AknS] @BSDAUTH_USAGE@[-g groupname|#gid] [-p prompt] [-U username] [-u username|#uid] [-g groupname|#gid] [command]" +#define SUDO_USAGE4 " [-AbEHknPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []" +#define SUDO_USAGE5 " -e [-AknS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..." #endif /* _SUDO_USAGE_H */ diff --git a/sudoers.cat b/sudoers.cat index 8c7876d..1afd926 100644 --- a/sudoers.cat +++ b/sudoers.cat @@ -61,7 +61,7 @@ DDEESSCCRRIIPPTTIIOONN -1.7.0 December 3, 2008 1 +1.7.2 June 30, 2009 1 @@ -98,6 +98,7 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) '!'* '#'uid | '!'* '%'group | '!'* '+'netgroup | + '!'* '%:'nonunix_group | '!'* User_Alias A User_List is made up of one or more usernames, uids (prefixed with @@ -106,6 +107,35 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) operators. An odd number of '!' operators negate the value of the item; an even number just cancel each other out. + A username, group, netgroup and nonunix_groups 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. \x20 for space. + + The nonunix_group syntax depends on the underlying implementation. For + instance, the QAS AD backend supports the following formats: + + +o Group in the same domain: "Group Name" + + +o Group in any domain: "Group Name@FULLY.QUALIFIED.DOMAIN" + + +o Group SID: "S-1-2-34-5678901234-5678901234-5678901234-567" + + Note that quotes around group names are optional. Unquoted strings + must use a backslash (\) to escape spaces and the '@' symbol. + + + + +1.7.2 June 30, 2009 2 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + Runas_List ::= Runas_Member | Runas_Member ',' Runas_List @@ -125,18 +155,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Host_List ::= Host | Host ',' Host_List - - -1.7.0 December 3, 2008 2 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - - Host ::= '!'* hostname | '!'* ip_addr | '!'* network(/netmask)? | @@ -172,6 +190,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) other aliases. A commandname is a fully qualified filename which may include shell-style wildcards (see the Wildcards section below). A simple filename allows the user to run the command with any arguments + + + +1.7.2 June 30, 2009 3 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + he/she wishes. However, you may also specify command line arguments (including wildcards). Alternately, you can specify "" to indicate that the command may only be run wwiitthhoouutt command line arguments. A @@ -187,21 +217,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) to permit a user to run ssuuddoo with the --ee option (or as ssuuddooeeddiitt). It may take command line arguments just as a normal command does. - - - - - - -1.7.0 December 3, 2008 3 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - DDeeffaauullttss Certain configuration options may be changed from their default values @@ -241,33 +256,33 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) not exist in a list. Defaults entries are parsed in the following order: generic, host and - user Defaults first, then runas Defaults and finally command defaults. - See "SUDOERS OPTIONS" for a list of supported Defaults parameters. - UUsseerr SSppeecciiffiiccaattiioonn - User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \ - (':' Host_List '=' Cmnd_Spec_List)* +1.7.2 June 30, 2009 4 - Cmnd_Spec_List ::= Cmnd_Spec | - Cmnd_Spec ',' Cmnd_Spec_List - Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd - Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')' +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) -1.7.0 December 3, 2008 4 + user Defaults first, then runas Defaults and finally command defaults. + See "SUDOERS OPTIONS" for a list of supported Defaults parameters. + UUsseerr SSppeecciiffiiccaattiioonn + User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \ + (':' Host_List '=' Cmnd_Spec_List)* -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + Cmnd_Spec_List ::= Cmnd_Spec | + Cmnd_Spec ',' Cmnd_Spec_List + Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd + Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')' Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' | 'SETENV:' | 'NOSETENV:' ) @@ -276,7 +291,8 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) what user) on specified hosts. By default, commands are run as rroooott, but this can be changed on a per-command basis. - Let's break that down into its constituent parts: + The basic structure of a user specification is `who = where (as_whom) + what'. Let's break that down into its constituent parts: RRuunnaass__SSppeecc @@ -307,6 +323,17 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) It is also possible to override a Runas_Spec later on in an entry. If we modify the entry like so: + + +1.7.2 June 30, 2009 5 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm Then user ddggbb is now allowed to run _/_b_i_n_/_l_s as ooppeerraattoorr, but _/_b_i_n_/_k_i_l_l @@ -322,18 +349,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) device file with the dialer group. Note that in this example only the group will be set, the command still runs as user ttccmm. - - - -1.7.0 December 3, 2008 5 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \ /usr/local/bin/minicom @@ -374,31 +389,30 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) _N_O_E_X_E_C _a_n_d _E_X_E_C - If ssuuddoo has been compiled with _n_o_e_x_e_c support and the underlying - operating system supports it, the NOEXEC tag can be used to prevent a - dynamically-linked executable from running further commands itself. - In the following example, user aaaarroonn may run _/_u_s_r_/_b_i_n_/_m_o_r_e and - _/_u_s_r_/_b_i_n_/_v_i but shell escapes will be disabled. - aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi +1.7.2 June 30, 2009 6 - See the "PREVENTING SHELL ESCAPES" section below for more details on - how NOEXEC works and whether or not it will work on your system. - _S_E_T_E_N_V _a_n_d _N_O_S_E_T_E_N_V - -1.7.0 December 3, 2008 6 +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + If ssuuddoo has been compiled with _n_o_e_x_e_c support and the underlying + operating system supports it, the NOEXEC tag can be used to prevent a + dynamically-linked executable from running further commands itself. + In the following example, user aaaarroonn may run _/_u_s_r_/_b_i_n_/_m_o_r_e and + _/_u_s_r_/_b_i_n_/_v_i but shell escapes will be disabled. + aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + See the "PREVENTING SHELL ESCAPES" section below for more details on + how NOEXEC works and whether or not it will work on your system. + _S_E_T_E_N_V _a_n_d _N_O_S_E_T_E_N_V These tags override the value of the _s_e_t_e_n_v option on a per-command basis. Note that if SETENV has been set for a command, any environment @@ -412,8 +426,8 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) ssuuddoo allows shell-style _w_i_l_d_c_a_r_d_s (aka meta or glob characters) to be used in hostnames, pathnames and command line arguments in the _s_u_d_o_e_r_s - file. Wildcard matching is done via the PPOOSSIIXX _f_n_m_a_t_c_h(3) routine. - Note that these are _n_o_t regular expressions. + file. Wildcard matching is done via the PPOOSSIIXX _g_l_o_b(3) and _f_n_m_a_t_c_h(3) + routines. Note that these are _n_o_t regular expressions. * Matches any set of zero or more characters. @@ -426,9 +440,9 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) \x For any character "x", evaluates to "x". This is used to escape special characters such as: "*", "?", "[", and "}". - POSIX character classes may also be used if your system's _f_n_m_a_t_c_h(3) - function supports them. However, because the ':' character has special - meaning in _s_u_d_o_e_r_s, it must be escaped. For example: + POSIX character classes may also be used if your system's _g_l_o_b(3) and + _f_n_m_a_t_c_h(3) functions support them. However, because the ':' character + has special meaning in _s_u_d_o_e_r_s, it must be escaped. For example: /bin/ls [[\:alpha\:]]* @@ -440,6 +454,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) /usr/bin/* + + + +1.7.2 June 30, 2009 7 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + match _/_u_s_r_/_b_i_n_/_w_h_o but not _/_u_s_r_/_b_i_n_/_X_1_1_/_x_t_e_r_m. EExxcceeppttiioonnss ttoo wwiillddccaarrdd rruulleess @@ -453,34 +479,62 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) IInncclluuddiinngg ootthheerr ffiilleess ffrroomm wwiitthhiinn ssuuddooeerrss It is possible to include other _s_u_d_o_e_r_s files from within the _s_u_d_o_e_r_s - file currently being parsed using the #include directive, similar to + file currently being parsed using the #include and #includedir + directives. + This can be used, for example, to keep a site-wide _s_u_d_o_e_r_s file in + addition to a local, per-machine file. For the sake of this example + the site-wide _s_u_d_o_e_r_s will be _/_e_t_c_/_s_u_d_o_e_r_s and the per-machine one will + be _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l. To include _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l from within + _/_e_t_c_/_s_u_d_o_e_r_s we would use the following line in _/_e_t_c_/_s_u_d_o_e_r_s: + #include /etc/sudoers.local -1.7.0 December 3, 2008 7 + When ssuuddoo reaches this line it will suspend processing of the current + file (_/_e_t_c_/_s_u_d_o_e_r_s) and switch to _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l. Upon reaching + the end of _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l, the rest of _/_e_t_c_/_s_u_d_o_e_r_s 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. + The filename may include the %h escape, signifying the short form of + the hostname. I.e., if the machine's hostname is "xerxes", then + #include /etc/sudoers.%h + will cause ssuuddoo to include the file _/_e_t_c_/_s_u_d_o_e_r_s_._x_e_r_x_e_s. + The #includedir directive can be used to create a _s_u_d_o_._d directory that + the system package manager can drop _s_u_d_o_e_r_s rules into as part of + package installation. For example, given: -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + #includedir /etc/sudoers.d + ssuuddoo will read each file in _/_e_t_c_/_s_u_d_o_e_r_s_._d, skipping file names that + end in ~ or contain a . character to avoid causing problems with + package manager or editor temporary/backup files. Files are parsed in + sorted lexical order. That is, _/_e_t_c_/_s_u_d_o_e_r_s_._d_/_0_1___f_i_r_s_t will be parsed + before _/_e_t_c_/_s_u_d_o_e_r_s_._d_/_1_0___s_e_c_o_n_d. Be aware that because the sorting is + lexical, not numeric, _/_e_t_c_/_s_u_d_o_e_r_s_._d_/_1___w_h_o_o_p_s would be loaded aafftteerr + _/_e_t_c_/_s_u_d_o_e_r_s_._d_/_1_0___s_e_c_o_n_d. Using a consistent number of leading zeroes + in the file names can be used to avoid such problems. - the one used by the C preprocessor. This is useful, for example, for - keeping a site-wide _s_u_d_o_e_r_s file in addition to a per-machine local - one. For the sake of this example the site-wide _s_u_d_o_e_r_s will be - _/_e_t_c_/_s_u_d_o_e_r_s and the per-machine one will be _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l. To - include _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l from _/_e_t_c_/_s_u_d_o_e_r_s we would use the following - line in _/_e_t_c_/_s_u_d_o_e_r_s: + Note that unlike files included via #include, vviissuuddoo will not edit the - #include /etc/sudoers.local - When ssuuddoo reaches this line it will suspend processing of the current - file (_/_e_t_c_/_s_u_d_o_e_r_s) and switch to _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l. Upon reaching - the end of _/_e_t_c_/_s_u_d_o_e_r_s_._l_o_c_a_l, the rest of _/_e_t_c_/_s_u_d_o_e_r_s 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. + +1.7.2 June 30, 2009 8 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + + files in a #includedir directory unless one of them contains a syntax + error. It is still possible to run vviissuuddoo with the -f flag to edit the + files directly. OOtthheerr ssppeecciiaall cchhaarraacctteerrss aanndd rreesseerrvveedd wwoorrddss @@ -521,17 +575,6 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS FFllaaggss: - - -1.7.0 December 3, 2008 8 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - always_set_home If set, ssuuddoo will set the HOME environment variable to the home directory of the target user (which is root unless the --uu option is used). This effectively means @@ -544,6 +587,17 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) the PASSWD and NOPASSWD tags. This flag is _o_n by default. + + +1.7.2 June 30, 2009 9 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + closefrom_override If set, the user may use ssuuddoo's --CC option which overrides the default starting point at which ssuuddoo @@ -586,18 +640,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) qualified you shouldn't need to set _f_q_d_n. This flag is _o_f_f by default. - - - -1.7.0 December 3, 2008 9 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - ignore_dot If set, ssuuddoo will ignore '.' or '' (current dir) in the PATH environment variable; the PATH itself is not modified. This flag is _o_f_f by default. @@ -610,6 +652,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) operators who would attempt to add roles to _/_e_t_c_/_s_u_d_o_e_r_s. When this option is present, _/_e_t_c_/_s_u_d_o_e_r_s does not even need to exist. Since this + + + +1.7.2 June 30, 2009 10 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + option tells ssuuddoo how to behave when no specific LDAP entries have been matched, this sudoOption is only meaningful for the cn=defaults section. This flag is @@ -653,17 +707,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) invoking user is not in the _s_u_d_o_e_r_s file. This flag is _o_n by default. - - -1.7.0 December 3, 2008 10 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - noexec If set, all commands run via ssuuddoo will behave as if the NOEXEC tag has been set, unless overridden by a EXEC tag. See the description of _N_O_E_X_E_C _a_n_d _E_X_E_C below as @@ -675,6 +718,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) 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 + + + +1.7.2 June 30, 2009 11 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + disadvantage is that if the executable is simply not in the user's PATH, ssuuddoo will tell the user that they are not allowed to run it, which can be confusing. This @@ -687,13 +742,23 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) _p_a_s_s_p_r_o_m_p_t___o_v_e_r_r_i_d_e is set, _p_a_s_s_p_r_o_m_p_t will always be used. This flag is _o_f_f by default. - preserve_groups By default ssuuddoo will initialize the group vector to the - list of groups the target user is in. When + preserve_groups By default, ssuuddoo will initialize the group vector to + the list of groups the target user is in. When _p_r_e_s_e_r_v_e___g_r_o_u_p_s 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 _o_f_f by default. + pwfeedback By default, ssuuddoo 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 ssuuddoo has hung at + this point. When _p_w_f_e_e_d_b_a_c_k is set, ssuuddoo 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 _o_f_f by default. + requiretty If set, ssuuddoo will only run when the user is logged in to a real tty. When this flag is set, ssuuddoo can only be run from a login session and not via other means such @@ -718,10 +783,11 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) instead of the password of the invoking user. This flag is _o_f_f by default. + set_home If set and ssuuddoo is invoked with the --ss option the HOME -1.7.0 December 3, 2008 11 +1.7.2 June 30, 2009 12 @@ -730,7 +796,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - set_home If set and ssuuddoo is invoked with the --ss option the HOME environment variable will be set to the home directory of the target user (which is root unless the --uu option is used). This effectively makes the --ss option imply @@ -762,6 +827,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) shell listed in the invoking user's /etc/passwd entry if not). This flag is _o_f_f by default. + fast_glob Normally, ssuuddoo uses the _g_l_o_b(3) function to do shell- + style globbing when matching pathnames. However, since + it accesses the file system, _g_l_o_b(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 (automounted). The _f_a_s_t___g_l_o_b option + causes ssuuddoo to use the _f_n_m_a_t_c_h(3) function, which does + not access the file system to do its matching. The + disadvantage of _f_a_s_t___g_l_o_b is that it is unable to match + relative pathnames such as _._/_l_s or _._._/_b_i_n_/_l_s. This + flag is _o_f_f by default. + stay_setuid Normally, when ssuuddoo executes a command the real and effective UIDs are set to the target user (root by default). This option changes that behavior such that @@ -773,21 +850,10 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) with either the _s_e_t_r_e_u_i_d_(_) or _s_e_t_r_e_s_u_i_d_(_) function. This flag is _o_f_f by default. - targetpw If set, ssuuddoo will prompt for the password of the user - specified by the --uu option (defaults to root) instead - of the password of the invoking user. Note that this - precludes the use of a uid not listed in the passwd - database as an argument to the --uu option. This flag is - _o_f_f by default. - tty_tickets If set, users must authenticate on a per-tty basis. - Normally, ssuuddoo uses a directory in the ticket dir with - the same name as the user running it. With this flag - enabled, ssuuddoo will use a file named for the tty the - -1.7.0 December 3, 2008 12 +1.7.2 June 30, 2009 13 @@ -796,9 +862,28 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + targetpw If set, ssuuddoo will prompt for the password of the user + specified by the --uu option (defaults to root) instead + of the password of the invoking user. Note that this + precludes the use of a uid not listed in the passwd + database as an argument to the --uu option. This flag is + _o_f_f by default. + + tty_tickets If set, users must authenticate on a per-tty basis. + Normally, ssuuddoo uses a directory in the ticket dir with + the same name as the user running it. With this flag + enabled, ssuuddoo will use a file named for the tty the user is logged in on in that directory. This flag is _o_f_f by default. + umask_override If set, ssuuddoo will set the umask as specified by _s_u_d_o_e_r_s + without modification. This makes it possible to + specify a more permissive umask in _s_u_d_o_e_r_s than the + user's own umask and matches historical behavior. If + _u_m_a_s_k___o_v_e_r_r_i_d_e is not set, ssuuddoo will set the umask to + be the union of the user's umask and what is specified + in _s_u_d_o_e_r_s. This flag is _o_f_f by default. + use_loginclass If set, ssuuddoo will apply the defaults specified for the target user's login class if one exists. Only available if ssuuddoo is configured with the @@ -831,6 +916,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) 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 80 (use 0 or negate + + + +1.7.2 June 30, 2009 14 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + the option to disable word wrap). passwd_timeout Number of minutes before the ssuuddoo password prompt times @@ -850,18 +947,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) option or set it to 0777 to preserve the user's umask. The actual umask that is used will be the union of the user's umask and 0022. This guarantees that ssuuddoo never - - - -1.7.0 December 3, 2008 13 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - lowers the umask when running a command. Note on systems that use PAM, the default PAM configuration may specify its own umask which will override the value set @@ -897,6 +982,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) escapes are supported: %H expanded to the local hostname including the domain + + + +1.7.2 June 30, 2009 15 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + name (on if the machine's hostname is fully qualified or the _f_q_d_n option is set) @@ -917,17 +1014,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) The default value is Password:. - - -1.7.0 December 3, 2008 14 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - runas_default The default user to run commands as if the --uu option is not specified on the command line. This defaults to root. Note that if _r_u_n_a_s___d_e_f_a_u_l_t is set it mmuusstt occur @@ -962,37 +1048,38 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) variable. env_file The _e_n_v___f_i_l_e options 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 be of - the form VARIABLE=value. Variables in this file are - subject to other ssuuddoo environment settings such as _e_n_v___k_e_e_p - and _e_n_v___c_h_e_c_k. - exempt_group - Users in this group are exempt from password and PATH - requirements. This is not set by default. - lecture This option controls when a short lecture will be printed - along with the password prompt. It has the following - possible values: - always Always lecture the user. +1.7.2 June 30, 2009 16 - never Never lecture the user. - once Only lecture the user the first time they run ssuuddoo. +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) -1.7.0 December 3, 2008 15 + 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 VARIABLE=value or export VARIABLE=value. + The value may optionally be surrounded by single or double + quotes. Variables in this file are subject to other ssuuddoo + environment settings such as _e_n_v___k_e_e_p and _e_n_v___c_h_e_c_k. + exempt_group + Users in this group are exempt from password and PATH + requirements. This is not set by default. + lecture This option controls when a short lecture will be printed + along with the password prompt. It has the following + possible values: + always Always lecture the user. -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + never Never lecture the user. + once Only lecture the user the first time they run ssuuddoo. If no value is specified, a value of _o_n_c_e is implied. Negating the option results in a value of _n_e_v_e_r being used. @@ -1027,6 +1114,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) logfile Path to the ssuuddoo log file (not the syslog log file). Setting a path turns on logging to a file; negating this + + + +1.7.2 June 30, 2009 17 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + option turns it off. By default, ssuuddoo logs via syslog. mailerflags Flags to use when invoking mailer. Defaults to --tt. @@ -1048,18 +1147,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) environment variable you may want to use this. Another use is if you want to have the "root path" be separate from the "user path." Users in the group specified by the - - - -1.7.0 December 3, 2008 16 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - _e_x_e_m_p_t___g_r_o_u_p option are not affected by _s_e_c_u_r_e___p_a_t_h. This is not set by default. @@ -1093,6 +1180,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) env_check Environment variables to be removed from the user's environment if the variable's value contains % or / characters. This can be used to guard against printf- + + + +1.7.2 June 30, 2009 18 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + style format vulnerabilities in poorly-written programs. The argument may be a double-quoted, space- separated list or a single value without double-quotes. @@ -1106,28 +1205,16 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) is run by root with the _-_V option. env_delete Environment variables to be removed from the user's - environment. 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 =, +=, -=, and ! - operators respectively. The default list of - environment variables to remove is displayed when ssuuddoo - is run by root with the _-_V option. Note that many - operating systems will remove potentially dangerous - - - -1.7.0 December 3, 2008 17 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - - variables from the environment of any setuid process - (such as ssuuddoo). + environment when the _e_n_v___r_e_s_e_t 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 =, +=, -=, and ! operators respectively. The + default list of environment variables to remove is + displayed when ssuuddoo is run by root with the _-_V option. + Note that many operating systems will remove + potentially dangerous variables from the environment of + any setuid process (such as ssuuddoo). env_keep Environment variables to be preserved in the user's environment when the _e_n_v___r_e_s_e_t option is in effect. @@ -1158,6 +1245,19 @@ EEXXAAMMPPLLEESS Below are example _s_u_d_o_e_r_s entries. Admittedly, some of these are a bit contrived. First, we define our _a_l_i_a_s_e_s: + + + + +1.7.2 June 30, 2009 19 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + # User alias specification User_Alias FULLTIMERS = millert, mikef, dowdy User_Alias PARTTIMERS = bostley, jwfox, crawl @@ -1166,6 +1266,7 @@ EEXXAAMMPPLLEESS # 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 :\ @@ -1180,18 +1281,6 @@ EEXXAAMMPPLLEESS # Cmnd alias specification Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\ /usr/sbin/restore, /usr/sbin/rrestore - - - -1.7.0 December 3, 2008 18 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - Cmnd_Alias KILL = /usr/bin/kill Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown @@ -1223,6 +1312,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Defaults!PAGERS noexec The _U_s_e_r _s_p_e_c_i_f_i_c_a_t_i_o_n is the part that actually determines who may run + + + +1.7.2 June 30, 2009 20 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + what. root ALL = (ALL) ALL @@ -1246,18 +1347,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) The user jjaacckk may run any command on the machines in the _C_S_N_E_T_S alias (the networks 128.138.243.0, 128.138.204.0, and 128.138.242.0). Of - - - -1.7.0 December 3, 2008 19 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - those networks, only 128.138.204.0 has an explicit netmask (in CIDR notation) indicating it is a class C network. For the other networks in _C_S_N_E_T_S, the local machine's netmask will be used during matching. @@ -1281,10 +1370,26 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root + %opers ALL = (: ADMINGRP) /usr/sbin/ + + Users in the ooppeerrss group may run commands in _/_u_s_r_/_s_b_i_n_/ as themselves + with any group in the _A_D_M_I_N_G_R_P Runas_Alias (the aaddmm and ooppeerr groups). + The user ppeettee is allowed to change anyone's password except for root on the _H_P_P_A machines. Note that this assumes _p_a_s_s_w_d(1) does not take multiple usernames on the command line. + + +1.7.2 June 30, 2009 21 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + bob SPARC = (OP) ALL : SGI = (OP) ALL The user bboobb may run anything on the _S_P_A_R_C and _S_G_I machines as any user @@ -1313,17 +1418,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) jen ALL, !SERVERS = ALL - - -1.7.0 December 3, 2008 20 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - The user jjeenn may run any command on any machine except for those in the _S_E_R_V_E_R_S Host_Alias (master, mail, www and ns). @@ -1349,6 +1443,19 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) and wim), may run any command as user www (which owns the web pages) or simply _s_u(1) to www. + + + + +1.7.2 June 30, 2009 22 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\ /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM @@ -1379,17 +1486,6 @@ PPRREEVVEENNTTIINNGG SSHHEELLLL EESSCCAAPPEESS that permit shell escapes include shells (obviously), editors, paginators, mail and terminal programs. - - -1.7.0 December 3, 2008 21 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - There are two basic approaches to this problem: restrict Avoid giving users access to commands that allow the user to @@ -1414,6 +1510,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) sudo -V | grep "dummy exec" + + + +1.7.2 June 30, 2009 23 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + If the resulting output contains a line that begins with: File containing dummy exec functions: @@ -1444,24 +1552,12 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Note that restricting shell escapes is not a panacea. Programs running as root are still capable of many potentially hazardous operations - - - -1.7.0 December 3, 2008 22 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - (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 ssuuddooeeddiitt. SSEEEE AALLSSOO - _r_s_h(1), _s_u(1), _f_n_m_a_t_c_h(3), _s_u_d_o(1m), _v_i_s_u_d_o(8) + _r_s_h(1), _s_u(1), _f_n_m_a_t_c_h(3), _g_l_o_b(3), _s_u_d_o(1m), _v_i_s_u_d_o(8) CCAAVVEEAATTSS The _s_u_d_o_e_r_s file should aallwwaayyss be edited by the vviissuuddoo command which @@ -1480,6 +1576,18 @@ BBUUGGSS SSUUPPPPOORRTT Limited free support is available via the sudo-users mailing list, see + + + +1.7.2 June 30, 2009 24 + + + + + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search the archives. @@ -1513,6 +1621,30 @@ DDIISSCCLLAAIIMMEERR -1.7.0 December 3, 2008 23 + + + + + + + + + + + + + + + + + + + + + + + + +1.7.2 June 30, 2009 25 diff --git a/sudoers.ldap.cat b/sudoers.ldap.cat index 8b581ff..234931d 100644 --- a/sudoers.ldap.cat +++ b/sudoers.ldap.cat @@ -26,17 +26,17 @@ DDEESSCCRRIIPPTTIIOONN prevent ssuuddoo from running. +o It is possible to specify per-entry options that override the - global default options. _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s 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. + global default options. _/_e_t_c_/_s_u_d_o_e_r_s 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. +o The vviissuuddoo program is no longer needed. vviissuuddoo provides locking - and syntax checking of the _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s 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. + and syntax checking of the _/_e_t_c_/_s_u_d_o_e_r_s 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. Another major difference between LDAP and file-based _s_u_d_o_e_r_s is that in LDAP, ssuuddoo-specific Aliases are not supported. @@ -61,7 +61,7 @@ DDEESSCCRRIIPPTTIIOONN -1.7.0 October 24, 2008 1 +1.7.2 June 11, 2009 1 @@ -71,8 +71,8 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) found, the multi-valued sudoOption attribute is parsed in the same - manner as a global Defaults line in _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s. In the - following example, the SSH_AUTH_SOCK variable will be preserved in the + manner as a global Defaults line in _/_e_t_c_/_s_u_d_o_e_r_s. In the following + example, the SSH_AUTH_SOCK variable will be preserved in the environment for all users. dn: cn=defaults,ou=SUDOers,dc=example,dc=com @@ -127,7 +127,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -1.7.0 October 24, 2008 2 +1.7.2 June 11, 2009 2 @@ -193,7 +193,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -1.7.0 October 24, 2008 3 +1.7.2 June 11, 2009 3 @@ -240,26 +240,26 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) CCoonnffiigguurriinngg llddaapp..ccoonnff - Sudo reads the _@_l_d_a_p___c_o_n_f_@ file for LDAP-specific configuration. + Sudo reads the _/_e_t_c_/_l_d_a_p_._c_o_n_f file for LDAP-specific configuration. Typically, this file is shared amongst different LDAP-aware clients. As such, most of the settings are not ssuuddoo-specific. Note that ssuuddoo - parses _@_l_d_a_p___c_o_n_f_@ itself and may support options that differ from + parses _/_e_t_c_/_l_d_a_p_._c_o_n_f itself and may support options that differ from those described in the _l_d_a_p_._c_o_n_f(4) manual. Also note that on systems using the OpenLDAP libraries, default values specified in _/_e_t_c_/_o_p_e_n_l_d_a_p_/_l_d_a_p_._c_o_n_f or the user's _._l_d_a_p_r_c files are not used. - Only those options explicitly listed in _@_l_d_a_p___c_o_n_f_@ that are supported - by ssuuddoo are honored. Configuration options are listed below in upper - case but are parsed in a case-independent manner. + Only those options explicitly listed in _/_e_t_c_/_l_d_a_p_._c_o_n_f that are + supported by ssuuddoo are honored. Configuration options are listed below + in upper case but are parsed in a case-independent manner. UURRII ldap[s]://[hostname[:port]] ... Specifies a whitespace-delimited list of one or more URIs -1.7.0 October 24, 2008 4 +1.7.2 June 11, 2009 4 @@ -325,7 +325,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -1.7.0 October 24, 2008 5 +1.7.2 June 11, 2009 5 @@ -343,8 +343,8 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) The RROOOOTTBBIINNDDDDNN parameter specifies the identity, in the form of a Distinguished Name (DN), to use when performing privileged LDAP operations, such as _s_u_d_o_e_r_s queries. The password corresponding to - the identity should be stored in _@_l_d_a_p___s_e_c_r_e_t_@. If not specified, - the BBIINNDDDDNN identity is used (if any). + the identity should be stored in _/_e_t_c_/_l_d_a_p_._s_e_c_r_e_t. If not + specified, the BBIINNDDDDNN identity is used (if any). LLDDAAPP__VVEERRSSIIOONN number The version of the LDAP protocol to use when connecting to the @@ -391,7 +391,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -1.7.0 October 24, 2008 6 +1.7.2 June 11, 2009 6 @@ -457,7 +457,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -1.7.0 October 24, 2008 7 +1.7.2 June 11, 2009 7 @@ -471,7 +471,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) CCoonnffiigguurriinngg nnsssswwiittcchh..ccoonnff Unless it is disabled at build time, ssuuddoo consults the Name Service - Switch file, _@_n_s_s_w_i_t_c_h___c_o_n_f_@, to specify the _s_u_d_o_e_r_s search order. + Switch file, _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f, to specify the _s_u_d_o_e_r_s search order. Sudo looks for a line beginning with sudoers: and uses this to determine the search order. Note that ssuuddoo does not stop searching after the first match and later matches take precedence over earlier @@ -494,18 +494,60 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) sudoers: ldap - If the _@_n_s_s_w_i_t_c_h___c_o_n_f_@ file is not present or there is no sudoers line, - the following default is assumed: + If the _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f file is not present or there is no sudoers + line, the following default is assumed: sudoers: files - Note that _@_n_s_s_w_i_t_c_h___c_o_n_f_@ is supported even when the underlying + Note that _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f is supported even when the underlying operating system does not use an nsswitch.conf file. + CCoonnffiigguurriinngg nneettssvvcc..ccoonnff + + On AIX systems, the _/_e_t_c_/_n_e_t_s_v_c_._c_o_n_f file is consulted instead of + _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f. ssuuddoo simply treats _n_e_t_s_v_c_._c_o_n_f as a variant of + _n_s_s_w_i_t_c_h_._c_o_n_f; information in the previous section unrelated to the + file format itself still applies. + + To consult LDAP first followed by the local sudoers file (if it + exists), use: + + sudoers = ldap, files + + The local _s_u_d_o_e_r_s file can be ignored completely by using: + + sudoers = ldap + + To treat LDAP as authoratative and only use the local sudoers file if + the user is not present in LDAP, use: + + + +1.7.2 June 11, 2009 8 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + sudoers = ldap = auth, files + + Note that in the above example, the auth qualfier only affects user + lookups; both LDAP and _s_u_d_o_e_r_s will be queried for Defaults entries. + + If the _/_e_t_c_/_n_e_t_s_v_c_._c_o_n_f file is not present or there is no sudoers + line, the following default is assumed: + + sudoers = files + FFIILLEESS - _@_l_d_a_p___c_o_n_f_@ LDAP configuration file + _/_e_t_c_/_l_d_a_p_._c_o_n_f LDAP configuration file + + _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f determines sudoers source order - _@_n_s_s_w_i_t_c_h___c_o_n_f_@ determines sudoers source order + _/_e_t_c_/_n_e_t_s_v_c_._c_o_n_f determines sudoers source order on AIX EEXXAAMMPPLLEESS EExxaammppllee llddaapp..ccoonnff @@ -520,18 +562,6 @@ EEXXAAMMPPLLEESS #port 389 # # URI will override the host and port settings. - - - -1.7.0 October 24, 2008 8 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - uri ldap://ldapserver #uri ldaps://secureldapserver #uri ldaps://secureldapserver ldap://ldapserver @@ -556,6 +586,18 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) # # LDAP protocol version, defaults to 3 #ldap_version 3 + + + +1.7.2 June 11, 2009 9 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + # # Define if you want to use an encrypted LDAP connection. # Typically, you must also set the port to 636 (ldaps). @@ -586,18 +628,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) # #tls_randfile /etc/egd-pool # - - - -1.7.0 October 24, 2008 9 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - # You may restrict which ciphers are used. Consult your SSL # documentation for which options go here. # Only supported when using OpenLDAP. @@ -615,12 +645,32 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) #tls_cert /etc/certs/client_cert.pem #tls_key /etc/certs/client_key.pem # - # For SunONE or iPlanet LDAP, the file 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/cert7.db - #tls_key /var/ldap/key3.db + # For SunONE or iPlanet 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. + + + +1.7.2 June 11, 2009 10 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + # + # 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 @@ -652,18 +702,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) attributetype ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' - - - -1.7.0 October 24, 2008 10 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) @@ -680,6 +718,18 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + + +1.7.2 June 11, 2009 11 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + attributetype ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' @@ -699,8 +749,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) sudoRunAsGroup $ sudoOption $ description ) ) - Add nsswitch.conf example? Add more exhaustive sudoers ldif example? - SSEEEE AALLSSOO _l_d_a_p_._c_o_n_f(4), _s_u_d_o_e_r_s(5) @@ -719,17 +767,6 @@ SSUUPPPPOORRTT http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search the archives. - - -1.7.0 October 24, 2008 11 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - DDIISSCCLLAAIIMMEERR ssuuddoo is provided ``AS IS'' and any express or implied warranties, including, but not limited to, the implied warranties of @@ -750,43 +787,6 @@ DDIISSCCLLAAIIMMEERR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1.7.0 October 24, 2008 12 +1.7.2 June 11, 2009 12 diff --git a/sudoers.ldap.man.in b/sudoers.ldap.man.in index 998786c..e4e172f 100644 --- a/sudoers.ldap.man.in +++ b/sudoers.ldap.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 2003-2008 +.\" Copyright (c) 2003-2009 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -14,7 +14,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Sudo: sudoers.ldap.man.in,v 1.11 2008/10/24 13:52:19 millert Exp $ +.\" $Sudo: sudoers.ldap.man.in,v 1.13 2009/06/11 20:29:12 millert Exp $ .\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: @@ -149,7 +149,7 @@ .\" ======================================================================== .\" .IX Title "SUDOERS.LDAP @mansectform@" -.TH SUDOERS.LDAP @mansectform@ "October 24, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.TH SUDOERS.LDAP @mansectform@ "June 11, 2009" "1.7.2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -176,13 +176,13 @@ It is still possible to have typos in a user or host name, but this will not prevent \fBsudo\fR from running. .IP "\(bu" 4 It is possible to specify per-entry options that override the global -default options. \fI\f(CI@sysconfdir\fI@/sudoers\fR only supports default options and +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. .IP "\(bu" 4 The \fBvisudo\fR program is no longer needed. \fBvisudo\fR provides -locking and syntax checking of the \fI\f(CI@sysconfdir\fI@/sudoers\fR file. +locking and syntax checking of the \fI@sysconfdir@/sudoers\fR file. Since \s-1LDAP\s0 updates are atomic, locking is no longer necessary. Because syntax is checked when the data is inserted into \s-1LDAP\s0, there is no need for a specialized tool to check syntax. @@ -208,7 +208,7 @@ container. .PP Sudo first looks for the \f(CW\*(C`cn=default\*(C'\fR entry in the SUDOers container. If found, the multi-valued \f(CW\*(C`sudoOption\*(C'\fR attribute is parsed in the -same manner as a global \f(CW\*(C`Defaults\*(C'\fR line in \fI\f(CI@sysconfdir\fI@/sudoers\fR. In +same manner as a global \f(CW\*(C`Defaults\*(C'\fR line in \fI@sysconfdir@/sudoers\fR. In the following example, the \f(CW\*(C`SSH_AUTH_SOCK\*(C'\fR variable will be preserved in the environment for all users. .PP @@ -357,17 +357,17 @@ The schema for \fBsudo\fR in OpenLDAP form is included in the \s-1EXAMPLES\s0 section. .Sh "Configuring ldap.conf" .IX Subsection "Configuring ldap.conf" -Sudo reads the \fI\f(CI@ldap_conf\fI@\fR file for LDAP-specific configuration. +Sudo reads the \fI@ldap_conf@\fR file for LDAP-specific configuration. Typically, this file is shared amongst different LDAP-aware clients. As such, most of the settings are not \fBsudo\fR\-specific. Note that -\&\fBsudo\fR parses \fI\f(CI@ldap_conf\fI@\fR itself and may support options +\&\fBsudo\fR parses \fI@ldap_conf@\fR itself and may support options that differ from those described in the \fIldap.conf\fR\|(@mansectform@) manual. .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 -Only those options explicitly listed in \fI\f(CI@ldap_conf\fI@\fR that are +Only those options explicitly listed in \fI@ldap_conf@\fR that are supported by \fBsudo\fR are honored. Configuration options are listed below in upper case but are parsed in a case-independent manner. .IP "\fB\s-1URI\s0\fR ldap[s]://[hostname[:port]] ..." 4 @@ -435,7 +435,7 @@ The \fB\s-1BINDPW\s0\fR parameter specifies the password to use when performing The \fB\s-1ROOTBINDDN\s0\fR parameter specifies the identity, in the form of a Distinguished Name (\s-1DN\s0), to use when performing privileged \s-1LDAP\s0 operations, such as \fIsudoers\fR queries. The password corresponding -to the identity should be stored in \fI\f(CI@ldap_secret\fI@\fR. +to the identity should be stored in \fI@ldap_secret@\fR. If not specified, the \fB\s-1BINDDN\s0\fR identity is used (if any). .IP "\fB\s-1LDAP_VERSION\s0\fR number" 4 .IX Item "LDAP_VERSION number" @@ -541,8 +541,8 @@ See the \f(CW\*(C`ldap.conf\*(C'\fR entry in the \s-1EXAMPLES\s0 section. .Sh "Configuring nsswitch.conf" .IX Subsection "Configuring nsswitch.conf" Unless it is disabled at build time, \fBsudo\fR consults the Name -Service Switch file, \fI\f(CI@nsswitch_conf\fI@\fR, to specify the \fIsudoers\fR -search order. Sudo looks for a line beginning with \f(CW\*(C`sudoers:\*(C'\fR and +Service Switch file, \fI@nsswitch_conf@\fR, to specify the \fIsudoers\fR +search order. Sudo looks for a line beginning with \f(CW\*(C`sudoers\*(C'\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. @@ -570,25 +570,66 @@ The local \fIsudoers\fR file can be ignored completely by using: \& sudoers: ldap .Ve .PP -If the \fI\f(CI@nsswitch_conf\fI@\fR file is not present or there is no +If the \fI@nsswitch_conf@\fR file is not present or there is no sudoers line, the following default is assumed: .PP .Vb 1 \& sudoers: files .Ve .PP -Note that \fI\f(CI@nsswitch_conf\fI@\fR is supported even when the underlying +Note that \fI@nsswitch_conf@\fR is supported even when the underlying operating system does not use an nsswitch.conf file. +.Sh "Configuring netsvc.conf" +.IX Subsection "Configuring netsvc.conf" +On \s-1AIX\s0 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 \s-1LDAP\s0 first followed by the local sudoers file (if it +exists), use: +.PP +.Vb 1 +\& sudoers = ldap, files +.Ve +.PP +The local \fIsudoers\fR file can be ignored completely by using: +.PP +.Vb 1 +\& sudoers = ldap +.Ve +.PP +To treat \s-1LDAP\s0 as authoratative and only use the local sudoers file +if the user is not present in \s-1LDAP\s0, use: +.PP +.Vb 1 +\& sudoers = ldap = auth, files +.Ve +.PP +Note that in the above example, the \f(CW\*(C`auth\*(C'\fR qualfier only affects +user lookups; both \s-1LDAP\s0 and \fIsudoers\fR will be queried for \f(CW\*(C`Defaults\*(C'\fR +entries. +.PP +If the \fI@netsvc_conf@\fR file is not present or there is no +sudoers line, the following default is assumed: +.PP +.Vb 1 +\& sudoers = files +.Ve .SH "FILES" .IX Header "FILES" -.ie n .IP "\fI\fI@ldap_conf\fI@\fR" 24 -.el .IP "\fI\f(CI@ldap_conf\fI@\fR" 24 +.ie n .IP "\fI@ldap_conf@\fR" 24 +.el .IP "\fI@ldap_conf@\fR" 24 .IX Item "@ldap_conf@" \&\s-1LDAP\s0 configuration file -.ie n .IP "\fI\fI@nsswitch_conf\fI@\fR" 24 -.el .IP "\fI\f(CI@nsswitch_conf\fI@\fR" 24 +.ie n .IP "\fI@nsswitch_conf@\fR" 24 +.el .IP "\fI@nsswitch_conf@\fR" 24 .IX Item "@nsswitch_conf@" determines sudoers source order +.ie n .IP "\fI@netsvc_conf@\fR" 24 +.el .IP "\fI@netsvc_conf@\fR" 24 +.IX Item "@netsvc_conf@" +determines sudoers source order on \s-1AIX\s0 .SH "EXAMPLES" .IX Header "EXAMPLES" .Sh "Example ldap.conf" @@ -675,12 +716,20 @@ determines sudoers source order \& #tls_cert /etc/certs/client_cert.pem \& #tls_key /etc/certs/client_key.pem \& # -\& # For SunONE or iPlanet LDAP, the file specified by tls_cert may -\& # contain CA certs and/or the client\*(Aqs cert. If the client\*(Aqs -\& # 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/cert7.db -\& #tls_key /var/ldap/key3.db +\& # For SunONE or iPlanet 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\*(Aqs cert. If the client\*(Aqs 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 @@ -748,9 +797,6 @@ schema directory (e.g. \fI/etc/openldap/schema\fR), add the proper \& sudoRunAsGroup $ sudoOption $ description ) \& ) .Ve -.PP -Add nsswitch.conf example? -Add more exhaustive sudoers ldif example? .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIldap.conf\fR\|(@mansectform@), \fIsudoers\fR\|(5) diff --git a/sudoers.ldap.pod b/sudoers.ldap.pod index 3b36ddd..7d59cb2 100644 --- a/sudoers.ldap.pod +++ b/sudoers.ldap.pod @@ -1,4 +1,4 @@ -Copyright (c) 2003-2008 +Copyright (c) 2003-2009 Todd C. Miller Permission to use, copy, modify, and distribute this software for any @@ -14,7 +14,7 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -$Sudo: sudoers.ldap.pod,v 1.10 2008/05/10 13:18:47 millert Exp $ +$Sudo: sudoers.ldap.pod,v 1.14 2009/05/29 13:43:12 millert Exp $ =pod =head1 NAME @@ -457,7 +457,7 @@ See the C entry in the L section. Unless it is disabled at build time, B consults the Name Service Switch file, F<@nsswitch_conf@>, to specify the I -search order. Sudo looks for a line beginning with C and +search order. Sudo looks for a line beginning with C: and uses this to determine the search order. Note that B does not stop searching after the first match and later matches take precedence over earlier ones. @@ -487,6 +487,36 @@ sudoers line, the following default is assumed: Note that F<@nsswitch_conf@> is supported even when the underlying operating system does not use an nsswitch.conf file. +=head2 Configuring netsvc.conf + +On AIX systems, the F<@netsvc_conf@> file is consulted instead of +F<@nsswitch_conf@>. B simply treats I as a +variant of I; information in the previous section +unrelated to the file format itself still applies. + +To consult LDAP first followed by the local sudoers file (if it +exists), use: + + sudoers = ldap, files + +The local I file can be ignored completely by using: + + sudoers = ldap + +To treat LDAP as authoratative and only use the local sudoers file +if the user is not present in LDAP, use: + + sudoers = ldap = auth, files + +Note that in the above example, the C qualfier only affects +user lookups; both LDAP and I will be queried for C +entries. + +If the F<@netsvc_conf@> file is not present or there is no +sudoers line, the following default is assumed: + + sudoers = files + =head1 FILES =over 24 @@ -499,6 +529,10 @@ LDAP configuration file determines sudoers source order +=item F<@netsvc_conf@> + +determines sudoers source order on AIX + =back =head1 EXAMPLES @@ -586,12 +620,20 @@ determines sudoers source order #tls_cert /etc/certs/client_cert.pem #tls_key /etc/certs/client_key.pem # - # For SunONE or iPlanet LDAP, the file 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/cert7.db - #tls_key /var/ldap/key3.db + # For SunONE or iPlanet 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 @@ -658,11 +700,6 @@ C line in C and restart B. sudoRunAsGroup $ sudoOption $ description ) ) -=for comment - -Add nsswitch.conf example? -Add more exhaustive sudoers ldif example? - =head1 SEE ALSO L, L diff --git a/sudoers.man.in b/sudoers.man.in index 533c8c7..60d56ed 100644 --- a/sudoers.man.in +++ b/sudoers.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994-1996, 1998-2005, 2007-2008 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2009 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.\" $Sudo: sudoers.man.in,v 1.74 2008/12/03 20:58:41 millert Exp $ +.\" $Sudo: sudoers.man.in,v 1.80 2009/06/30 12:41:09 millert Exp $ .\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: @@ -153,7 +153,7 @@ .\" ======================================================================== .\" .IX Title "SUDOERS @mansectform@" -.TH SUDOERS @mansectform@ "December 3, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.TH SUDOERS @mansectform@ "June 30, 2009" "1.7.2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -254,6 +254,7 @@ The definitions of what constitutes a valid \fIalias\fR member follow. \& \*(Aq!\*(Aq* \*(Aq#\*(Aquid | \& \*(Aq!\*(Aq* \*(Aq%\*(Aqgroup | \& \*(Aq!\*(Aq* \*(Aq+\*(Aqnetgroup | +\& \*(Aq!\*(Aq* \*(Aq%:\*(Aqnonunix_group | \& \*(Aq!\*(Aq* User_Alias .Ve .PP @@ -263,6 +264,23 @@ with '+') and \f(CW\*(C`User_Alias\*(C'\fRes. Each list item may be prefixed wi zero or more '!' operators. An odd number of '!' operators negate the value of the item; an even number just cancel each other out. .PP +A \f(CW\*(C`username\*(C'\fR, \f(CW\*(C`group\*(C'\fR, \f(CW\*(C`netgroup\*(C'\fR and \f(CW\*(C`nonunix_groups\*(C'\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. +.PP +The \f(CW\*(C`nonunix_group\*(C'\fR syntax depends on the underlying implementation. +For instance, the \s-1QAS\s0 \s-1AD\s0 backend supports the following formats: +.IP "\(bu" 4 +Group in the same domain: \*(L"Group Name\*(R" +.IP "\(bu" 4 +Group in any domain: \*(L"Group Name@FULLY.QUALIFIED.DOMAIN\*(R" +.IP "\(bu" 4 +Group \s-1SID:\s0 \*(L"S\-1\-2\-34\-5678901234\-5678901234\-5678901234\-567\*(R" +.PP +Note that quotes around group names are optional. Unquoted strings must +use a backslash (\e) to escape spaces and the '@' symbol. +.PP .Vb 2 \& Runas_List ::= Runas_Member | \& Runas_Member \*(Aq,\*(Aq Runas_List @@ -396,7 +414,7 @@ See \*(L"\s-1SUDOERS\s0 \s-1OPTIONS\s0\*(R" for a list of supported Defaults par \& \& Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd \& -\& Runas_Spec ::= \*(Aq(\*(Aq Runas_List? (: Runas_List)? \*(Aq)\*(Aq +\& Runas_Spec ::= \*(Aq(\*(Aq Runas_List? (\*(Aq:\*(Aq Runas_List)? \*(Aq)\*(Aq \& \& Tag_Spec ::= (\*(AqNOPASSWD:\*(Aq | \*(AqPASSWD:\*(Aq | \*(AqNOEXEC:\*(Aq | \*(AqEXEC:\*(Aq | \& \*(AqSETENV:\*(Aq | \*(AqNOSETENV:\*(Aq ) @@ -406,7 +424,8 @@ 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 -Let's break that down into its constituent parts: +The basic structure of a user specification is `who = where (as_whom) +what'. Let's break that down into its constituent parts: .Sh "Runas_Spec" .IX Subsection "Runas_Spec" A \f(CW\*(C`Runas_Spec\*(C'\fR determines the user and/or the group that a command @@ -539,9 +558,10 @@ be overridden by use of the \f(CW\*(C`UNSETENV\*(C'\fR tag. .Sh "Wildcards" .IX Subsection "Wildcards" \&\fBsudo\fR allows shell-style \fIwildcards\fR (aka meta or glob characters) -to be used in hostnames, pathnames and command line arguments in the -\&\fIsudoers\fR file. Wildcard matching is done via the \fB\s-1POSIX\s0\fR -\&\fIfnmatch\fR\|(3) routine. Note that these are \fInot\fR regular expressions. +to be used in hostnames, pathnames and command line arguments in +the \fIsudoers\fR file. Wildcard matching is done via the \fB\s-1POSIX\s0\fR +\&\fIglob\fR\|(3) and \fIfnmatch\fR\|(3) routines. Note that these are \fInot\fR +regular expressions. .ie n .IP "\*(C`*\*(C'" 8 .el .IP "\f(CW\*(C`*\*(C'\fR" 8 .IX Item "*" @@ -564,10 +584,10 @@ Matches any character \fBnot\fR in the specified range. For any character \*(L"x\*(R", evaluates to \*(L"x\*(R". This is used to escape special characters such as: \*(L"*\*(R", \*(L"?\*(R", \*(L"[\*(R", and \*(L"}\*(R". .PP -\&\s-1POSIX\s0 character classes may also be used if your system's -\&\fIfnmatch\fR\|(3) function supports them. However, because the -\&\f(CW\*(Aq:\*(Aq\fR character has special meaning in \fIsudoers\fR, it must -be escaped. For example: +\&\s-1POSIX\s0 character classes may also be used if your system's \fIglob\fR\|(3) +and \fIfnmatch\fR\|(3) functions support them. However, because the +\&\f(CW\*(Aq:\*(Aq\fR character has special meaning in \fIsudoers\fR, it must be +escaped. For example: .PP .Vb 1 \& /bin/ls [[\e:alpha\e:]]* @@ -597,17 +617,19 @@ with \fBany\fR arguments. .Sh "Including other files from within sudoers" .IX Subsection "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 \f(CW\*(C`#include\*(C'\fR -directive, similar to the one used by the C preprocessor. This is -useful, for example, for keeping a site-wide \fIsudoers\fR file in -addition to a per-machine local one. For the sake of this example -the site-wide \fIsudoers\fR 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 \fI/etc/sudoers\fR we would use the following line in \fI/etc/sudoers\fR: -.PP -.Vb 1 -\& #include /etc/sudoers.local -.Ve +\&\fIsudoers\fR file currently being parsed using the \f(CW\*(C`#include\*(C'\fR and +\&\f(CW\*(C`#includedir\*(C'\fR directives. +.PP +This 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 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 we would use the +following line in \fI/etc/sudoers\fR: +.Sp +.RS 4 +\&\f(CW\*(C`#include /etc/sudoers.local\*(C'\fR +.RE .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. @@ -615,6 +637,35 @@ 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 filename may include the \f(CW%h\fR escape, signifying the short form +of the hostname. I.e., if the machine's hostname is \*(L"xerxes\*(R", then +.PP +\&\f(CW\*(C`#include /etc/sudoers.%h\*(C'\fR +.PP +will cause \fBsudo\fR to include the file \fI/etc/sudoers.xerxes\fR. +.PP +The \f(CW\*(C`#includedir\*(C'\fR directive can be used to create a \fIsudo.d\fR +directory that the system package manager can drop \fIsudoers\fR rules +into as part of package installation. For example, given: +.PP +\&\f(CW\*(C`#includedir /etc/sudoers.d\*(C'\fR +.PP +\&\fBsudo\fR will read each file in \fI/etc/sudoers.d\fR, skipping file +names that end in \f(CW\*(C`~\*(C'\fR or contain a \f(CW\*(C`.\*(C'\fR 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 +\&\fBafter\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. +.PP +Note that unlike files included via \f(CW\*(C`#include\*(C'\fR, \fBvisudo\fR will not +edit the files in a \f(CW\*(C`#includedir\*(C'\fR directory unless one of them +contains a syntax error. It is still possible to run \fBvisudo\fR +with the \f(CW\*(C`\-f\*(C'\fR flag to edit the files directly. .Sh "Other special characters and reserved words" .IX Subsection "Other special characters and reserved words" The pound sign ('#') is used to indicate a comment (unless it is @@ -787,11 +838,21 @@ the string \*(L"Password:\*(R". If \fIpassprompt_override\fR is set, \fIpasspro will always be used. This flag is \fIoff\fR by default. .IP "preserve_groups" 16 .IX Item "preserve_groups" -By default \fBsudo\fR will initialize the group vector to the list of +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. +.IP "pwfeedback" 16 +.IX Item "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. .IP "requiretty" 16 .IX Item "requiretty" If set, \fBsudo\fR will only run when the user is logged in to a real @@ -848,6 +909,17 @@ If set and \fBsudo\fR is invoked with no arguments it acts as if the shell is determined by the \f(CW\*(C`SHELL\*(C'\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. +.IP "fast_glob" 16 +.IX Item "fast_glob" +Normally, \fBsudo\fR uses the \fIglob\fR\|(3) function to do shell-style +globbing when matching pathnames. However, since it accesses the +file system, \fIglob\fR\|(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 (automounted). The \fIfast_glob\fR +option causes \fBsudo\fR to use the \fIfnmatch\fR\|(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 pathnames +such as \fI./ls\fR or \fI../bin/ls\fR. This flag is \fIoff\fR by default. .IP "stay_setuid" 16 .IX Item "stay_setuid" Normally, when \fBsudo\fR executes a command the real and effective @@ -872,6 +944,14 @@ If set, users must authenticate on a per-tty basis. Normally, the user running it. With this flag enabled, \fBsudo\fR will use a file named for the tty the user is logged in on in that directory. This flag is \fI@tty_tickets@\fR by default. +.IP "umask_override" 16 +.IX Item "umask_override" +If set, \fBsudo\fR will set the umask as specified by \fIsudoers\fR without +modification. This makes it possible to specify a more permissive +umask in \fIsudoers\fR 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 \fIoff\fR by default. @LCMAN@.IP "use_loginclass" 16 @LCMAN@.IX Item "use_loginclass" @LCMAN@If set, \fBsudo\fR will apply the defaults specified for the target user's @@ -1043,11 +1123,13 @@ The value of \fIaskpass\fR may be overridden by the \f(CW\*(C`SUDO_ASKPASS\*(C'\ environment variable. .IP "env_file" 12 .IX Item "env_file" -The \fIenv_file\fR options 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 be of the form \f(CW\*(C`VARIABLE=value\*(C'\fR. -Variables in this file are subject to other \fBsudo\fR environment -settings such as \fIenv_keep\fR and \fIenv_check\fR. +The \fIenv_file\fR options 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 +\&\f(CW\*(C`VARIABLE=value\*(C'\fR or \f(CW\*(C`export VARIABLE=value\*(C'\fR. The value may +optionally be surrounded by single or double quotes. Variables in +this file are subject to other \fBsudo\fR environment settings such +as \fIenv_keep\fR and \fIenv_check\fR. .IP "exempt_group" 12 .IX Item "exempt_group" Users in this group are exempt from password and \s-1PATH\s0 requirements. @@ -1183,15 +1265,16 @@ variables to check is displayed when \fBsudo\fR is run by root with the \fI\-V\fR option. .IP "env_delete" 16 .IX Item "env_delete" -Environment variables to be removed from the user's environment. -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 \f(CW\*(C`=\*(C'\fR, \f(CW\*(C`+=\*(C'\fR, \f(CW\*(C`\-=\*(C'\fR, and -\&\f(CW\*(C`!\*(C'\fR operators respectively. The default list of environment -variables to remove is displayed when \fBsudo\fR is run by root with the -\&\fI\-V\fR option. Note that many operating systems will remove potentially -dangerous variables from the environment of any setuid process (such -as \fBsudo\fR). +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 \f(CW\*(C`=\*(C'\fR, \f(CW\*(C`+=\*(C'\fR, \f(CW\*(C`\-=\*(C'\fR, and \f(CW\*(C`!\*(C'\fR operators +respectively. The default list of environment variables to remove +is displayed when \fBsudo\fR is run by root with the \fI\-V\fR option. +Note that many operating systems will remove potentially dangerous +variables from the environment of any setuid process (such as +\&\fBsudo\fR). .IP "env_keep" 16 .IX Item "env_keep" Environment variables to be preserved in the user's environment @@ -1236,6 +1319,7 @@ these are a bit contrived. First, we define our \fIaliases\fR: \& # 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 @@ -1346,8 +1430,14 @@ The user \fBjoe\fR may only \fIsu\fR\|(1) to operator. .PP .Vb 1 \& pete HPPA = /usr/bin/passwd [A\-Za\-z]*, !/usr/bin/passwd root +\& +\& %opers ALL = (: ADMINGRP) /usr/sbin/ .Ve .PP +Users in the \fBopers\fR group may run commands in \fI/usr/sbin/\fR as themselves +with any group in the \fI\s-1ADMINGRP\s0\fR \f(CW\*(C`Runas_Alias\*(C'\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 \fI\s-1HPPA\s0\fR machines. Note that this assumes \fIpasswd\fR\|(1) does not take multiple usernames on the command line. @@ -1524,7 +1614,7 @@ editor, a safer approach is to give the user permission to run \&\fBsudoedit\fR. .SH "SEE ALSO" .IX Header "SEE ALSO" -\&\fIrsh\fR\|(1), \fIsu\fR\|(1), \fIfnmatch\fR\|(3), \fIsudo\fR\|(@mansectsu@), \fIvisudo\fR\|(8) +\&\fIrsh\fR\|(1), \fIsu\fR\|(1), \fIfnmatch\fR\|(3), \fIglob\fR\|(3), \fIsudo\fR\|(@mansectsu@), \fIvisudo\fR\|(8) .SH "CAVEATS" .IX Header "CAVEATS" The \fIsudoers\fR file should \fBalways\fR be edited by the \fBvisudo\fR diff --git a/sudoers.pod b/sudoers.pod index 63c49cf..a55ce0e 100644 --- a/sudoers.pod +++ b/sudoers.pod @@ -1,4 +1,4 @@ -Copyright (c) 1994-1996, 1998-2005, 2007-2008 +Copyright (c) 1994-1996, 1998-2005, 2007-2009 Todd C. Miller Permission to use, copy, modify, and distribute this software for any @@ -18,7 +18,7 @@ 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. -$Sudo: sudoers.pod,v 1.155 2008/12/03 20:57:13 millert Exp $ +$Sudo: sudoers.pod,v 1.173 2009/06/30 12:41:09 millert Exp $ =pod =head1 NAME @@ -116,6 +116,7 @@ The definitions of what constitutes a valid I member follow. '!'* '#'uid | '!'* '%'group | '!'* '+'netgroup | + '!'* '%:'nonunix_group | '!'* User_Alias A C is made up of one or more usernames, uids (prefixed @@ -124,6 +125,33 @@ with '+') and Ces. Each list item may be prefixed with zero or more '!' operators. An odd number of '!' operators negate the value of the item; an even number just cancel each other out. +A C, C, C and C 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. \x20 for space. + +The C syntax depends on the underlying implementation. +For instance, the QAS AD backend supports the following formats: + +=over 4 + +=item * + +Group in the same domain: "Group Name" + +=item * + +Group in any domain: "Group Name@FULLY.QUALIFIED.DOMAIN" + +=item * + +Group SID: "S-1-2-34-5678901234-5678901234-5678901234-567" + +=back + +Note that quotes around group names are optional. Unquoted strings must +use a backslash (\) to escape spaces and the '@' symbol. + Runas_List ::= Runas_Member | Runas_Member ',' Runas_List @@ -238,7 +266,7 @@ Defaults entries are parsed in the following order: generic, host and user Defaults first, then runas Defaults and finally command defaults. -See L for a list of supported Defaults parameters. +See L<"SUDOERS OPTIONS"> for a list of supported Defaults parameters. =head2 User Specification @@ -250,7 +278,7 @@ See L for a list of supported Defaults parameters. Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd - Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')' + Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')' Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' | 'SETENV:' | 'NOSETENV:' ) @@ -259,7 +287,8 @@ A B determines which commands a user may run (and as what user) on specified hosts. By default, commands are run as B, but this can be changed on a per-command basis. -Let's break that down into its constituent parts: +The basic structure of a user specification is `who = where (as_whom) +what'. Let's break that down into its constituent parts: =head2 Runas_Spec @@ -376,9 +405,10 @@ be overridden by use of the C tag. =head2 Wildcards B allows shell-style I (aka meta or glob characters) -to be used in hostnames, pathnames and command line arguments in the -I file. Wildcard matching is done via the B -L routine. Note that these are I regular expressions. +to be used in hostnames, pathnames and command line arguments in +the I file. Wildcard matching is done via the B +L and L routines. Note that these are I +regular expressions. =over 8 @@ -405,10 +435,10 @@ escape special characters such as: "*", "?", "[", and "}". =back -POSIX character classes may also be used if your system's -L function supports them. However, because the -C<':'> character has special meaning in I, it must -be escaped. For example: +POSIX character classes may also be used if your system's L +and L functions support them. However, because the +C<':'> character has special meaning in I, it must be +escaped. For example: /bin/ls [[\:alpha\:]]* @@ -440,15 +470,21 @@ with B arguments. =head2 Including other files from within sudoers It is possible to include other I files from within the -I file currently being parsed using the C<#include> -directive, similar to the one used by the C preprocessor. This is -useful, for example, for keeping a site-wide I file in -addition to a per-machine local one. For the sake of this example -the site-wide I will be F and the per-machine -one will be F. To include F -from F we would use the following line in F: +I file currently being parsed using the C<#include> and +C<#includedir> directives. - #include /etc/sudoers.local +This can be used, for example, to keep a site-wide I file +in addition to a local, per-machine file. For the sake of this +example the site-wide I will be F and the +per-machine one will be F. To include +F from within F we would use the +following line in F: + +=over 4 + +C<#include /etc/sudoers.local> + +=back When B reaches this line it will suspend processing of the current file (F) and switch to F. @@ -457,6 +493,35 @@ F 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. +The filename may include the C<%h> escape, signifying the short form +of the hostname. I.e., if the machine's hostname is "xerxes", then + +C<#include /etc/sudoers.%h> + +will cause B to include the file F. + +The C<#includedir> directive can be used to create a F +directory that the system package manager can drop I rules +into as part of package installation. For example, given: + +C<#includedir /etc/sudoers.d> + +B will read each file in F, skipping file +names that end in C<~> or contain a C<.> character to avoid causing +problems with package manager or editor temporary/backup files. +Files are parsed in sorted lexical order. That is, +F will be parsed before +F. Be aware that because the sorting is +lexical, not numeric, F would be loaded +B F. Using a consistent number +of leading zeroes in the file names can be used to avoid such +problems. + +Note that unlike files included via C<#include>, B will not +edit the files in a C<#includedir> directory unless one of them +contains a syntax error. It is still possible to run B +with the C<-f> flag to edit the files directly. + =head2 Other special characters and reserved words The pound sign ('#') is used to indicate a comment (unless it is @@ -653,12 +718,23 @@ will always be used. This flag is I by default. =item preserve_groups -By default B will initialize the group vector to the list of +By default, B will initialize the group vector to the list of groups the target user is in. When I 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 I by default. +=item pwfeedback + +By default, B 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 B +has hung at this point. When I is set, B 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 I by default. + =item requiretty If set, B will only run when the user is logged in to a real @@ -723,6 +799,18 @@ shell is determined by the C 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 I by default. +=item fast_glob + +Normally, B uses the L function to do shell-style +globbing when matching pathnames. However, since it accesses the +file system, L can take a long time to complete for some +patterns, especially when the pattern references a network file +system that is mounted on demand (automounted). The I +option causes B to use the L function, which does +not access the file system to do its matching. The disadvantage +of I is that it is unable to match relative pathnames +such as F<./ls> or F<../bin/ls>. This flag is I by default. + =item stay_setuid Normally, when B executes a command the real and effective @@ -750,6 +838,15 @@ the user running it. With this flag enabled, B will use a file named for the tty the user is logged in on in that directory. This flag is I<@tty_tickets@> by default. +=item umask_override + +If set, B will set the umask as specified by I without +modification. This makes it possible to specify a more permissive +umask in I than the user's own umask and matches historical +behavior. If I is not set, B will set the +umask to be the union of the user's umask and what is specified in +I. This flag is I by default. + =item use_loginclass If set, B will apply the defaults specified for the target user's @@ -959,11 +1056,13 @@ environment variable. =item env_file -The I options 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 be of the form C. -Variables in this file are subject to other B environment -settings such as I and I. +The I options 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 +C or C. The value may +optionally be surrounded by single or double quotes. Variables in +this file are subject to other B environment settings such +as I and I. =item exempt_group @@ -1128,15 +1227,16 @@ the I<-V> option. =item env_delete -Environment variables to be removed from the user's environment. -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 C<=>, C<+=>, C<-=>, and -C operators respectively. The default list of environment -variables to remove is displayed when B is run by root with the -I<-V> option. Note that many operating systems will remove potentially -dangerous variables from the environment of any setuid process (such -as B). +Environment variables to be removed from the user's environment +when the I 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 C<=>, C<+=>, C<-=>, and C operators +respectively. The default list of environment variables to remove +is displayed when B is run by root with the I<-V> option. +Note that many operating systems will remove potentially dangerous +variables from the environment of any setuid process (such as +B). =item env_keep @@ -1190,6 +1290,7 @@ these are a bit contrived. First, we define our I: # 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 :\ @@ -1283,6 +1384,12 @@ The user B may only L to operator. pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root + %opers ALL = (: ADMINGRP) /usr/sbin/ + +Users in the B group may run commands in F as themselves +with any group in the I C (the B and B +groups). + The user B is allowed to change anyone's password except for root on the I machines. Note that this assumes L does not take multiple usernames on the command line. @@ -1438,7 +1545,7 @@ B. =head1 SEE ALSO -L, L, L, L, L +L, L, L, L, L, L =head1 CAVEATS diff --git a/term.c b/term.c new file mode 100644 index 0000000..d962fe6 --- /dev/null +++ b/term.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2009 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_TERMIOS_H +# include +#else +# ifdef HAVE_TERMIO_H +# include +# else +# include +# include +# endif /* HAVE_TERMIO_H */ +#endif /* HAVE_TERMIOS_H */ + +#include "sudo.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: term.c,v 1.4 2009/02/25 10:47:12 millert Exp $"; +#endif /* lint */ + +#ifndef TCSASOFT +# define TCSASOFT 0 +#endif +#ifndef ECHONL +# define ECHONL 0 +#endif +#ifndef IEXTEN +# define IEXTEN 0 +#endif + +#ifndef _POSIX_VDISABLE +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE 0 +# endif +#endif + +/* + * Compat macros for non-termios systems. + */ +#ifndef HAVE_TERMIOS_H +# ifdef HAVE_TERMIO_H +# undef termios +# define termios termio +# define tcgetattr(f, t) ioctl(f, TCGETA, t) +# define tcsetattr(f, a, t) ioctl(f, a, t) +# undef TCSAFLUSH +# define TCSAFLUSH TCSETAF +# else /* SGTTY */ +# undef termios +# define termios sgttyb +# define c_lflag sg_flags +# define tcgetattr(f, t) ioctl(f, TIOCGETP, t) +# define tcsetattr(f, a, t) ioctl(f, a, t) +# undef TCSAFLUSH +# define TCSAFLUSH TIOCSETP +# endif /* HAVE_TERMIO_H */ +#endif /* HAVE_TERMIOS_H */ + +typedef struct termios sudo_term_t; + +static sudo_term_t term, oterm; +static int changed; +int term_erase; +int term_kill; + +int +term_restore(fd) + int fd; +{ + if (changed) { + if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &oterm) != 0) + return(0); + changed = 0; + } + return(1); +} + +int +term_noecho(fd) + int fd; +{ + if (!changed && tcgetattr(fd, &oterm) != 0) + return(0); + (void) memcpy(&term, &oterm, sizeof(term)); + CLR(term.c_lflag, ECHO|ECHONL); +#ifdef VSTATUS + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &term) == 0) { + changed = 1; + return(1); + } + return(0); +} + +#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) +int +term_raw(fd) + int fd; +{ + if (!changed && tcgetattr(fd, &oterm) != 0) + return(0); + (void) memcpy(&term, &oterm, sizeof(term)); + /* Set terminal to half-cooked mode */ + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; + CLR(term.c_lflag, ECHO | ECHONL | ICANON | IEXTEN); + SET(term.c_lflag, ISIG); +#ifdef VSTATUS + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + if (tcsetattr(fd, TCSAFLUSH|TCSASOFT, &term) == 0) { + term_erase = term.c_cc[VERASE]; + term_kill = term.c_cc[VKILL]; + changed = 1; + return(1); + } + return(0); +} + +#else /* SGTTY */ + +int +term_raw(fd) + int fd; +{ + if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0) + return(0); + (void) memcpy(&term, &oterm, sizeof(term)); + /* Set terminal to half-cooked mode */ + CLR(term.c_lflag, ECHO); + SET(term.sg_flags, CBREAK); + if (ioctl(fd, TIOCSETP, &term) == 0) { + term_erase = term.sg_erase; + term_kill = term.sg_kill; + changed = 1; + return(1); + } + return(0); +} + +#endif diff --git a/testsudoers.c b/testsudoers.c index 0eaf1d7..c961432 100644 --- a/testsudoers.c +++ b/testsudoers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -71,7 +71,7 @@ #endif /* HAVE_FNMATCH */ #ifndef lint -__unused static const char rcsid[] = "$Sudo: testsudoers.c,v 1.128 2008/11/19 17:01:20 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: testsudoers.c,v 1.131 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ @@ -373,8 +373,9 @@ set_fqdn() } FILE * -open_sudoers(path, keepopen) +open_sudoers(path, isdir, keepopen) const char *path; + int isdir; int *keepopen; { return(fopen(path, "r")); @@ -386,11 +387,11 @@ init_envtables() return; } -void +int set_perms(perm) int perm; { - return; + return(1); } void diff --git a/tgetpass.c b/tgetpass.c index 62faead..503cb97 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -27,10 +27,6 @@ #include #include -#ifdef HAVE_SYS_BSDTYPES_H -# include -#endif /* HAVE_SYS_BSDTYPES_H */ -#include #include #ifdef STDC_HEADERS # include @@ -57,66 +53,23 @@ #include #include #include -#ifdef HAVE_TERMIOS_H -# include -#else -# ifdef HAVE_TERMIO_H -# include -# else -# include -# include -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.126 2008/12/09 20:55:49 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.131 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ -#ifndef TCSASOFT -# define TCSASOFT 0 -#endif -#ifndef ECHONL -# define ECHONL 0 -#endif - -#ifndef _POSIX_VDISABLE -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE 0 -# endif -#endif - -/* - * Compat macros for non-termios systems. - */ -#ifndef HAVE_TERMIOS_H -# ifdef HAVE_TERMIO_H -# undef termios -# define termios termio -# define tcgetattr(f, t) ioctl(f, TCGETA, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TCSETAF -# else -# undef termios -# define termios sgttyb -# define c_lflag sg_flags -# define tcgetattr(f, t) ioctl(f, TIOCGETP, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TIOCSETP -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ - static volatile sig_atomic_t signo; static void handler __P((int)); -static char *getln __P((int, char *, size_t)); +static char *getln __P((int, char *, size_t, int)); static char *sudo_askpass __P((const char *)); +extern int term_restore __P((int)); +extern int term_noecho __P((int)); +extern int term_raw __P((int)); + /* * Like getpass(3) but with timeout and echo flags. */ @@ -128,10 +81,9 @@ tgetpass(prompt, timeout, flags) { sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm; sigaction_t savetstp, savettin, savettou; - struct termios term, oterm; char *pass; static char buf[SUDO_PASS_MAX + 1]; - int input, output, save_errno; + int input, output, save_errno, neednl;; (void) fflush(stdout); @@ -167,19 +119,10 @@ restart: (void) sigaction(SIGTTIN, &sa, &savettin); (void) sigaction(SIGTTOU, &sa, &savettou); - /* Turn echo off/on as specified by flags. */ - if (tcgetattr(input, &oterm) == 0) { - (void) memcpy(&term, &oterm, sizeof(term)); - if (!ISSET(flags, TGP_ECHO)) - CLR(term.c_lflag, ECHO|ECHONL); -#ifdef VSTATUS - term.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif - (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); - } else { - zero_bytes(&term, sizeof(term)); - zero_bytes(&oterm, sizeof(oterm)); - } + if (def_pwfeedback) + neednl = term_raw(input); + else + neednl = term_noecho(input); /* No output if we are already backgrounded. */ if (signo != SIGTTOU && signo != SIGTTIN) { @@ -188,20 +131,16 @@ restart: if (timeout > 0) alarm(timeout); - pass = getln(input, buf, sizeof(buf)); + pass = getln(input, buf, sizeof(buf), def_pwfeedback); alarm(0); save_errno = errno; - if (!ISSET(term.c_lflag, ECHO)) + if (neednl) (void) write(output, "\n", 1); } /* Restore old tty settings and signals. */ - if (memcmp(&term, &oterm, sizeof(term)) != 0) { - while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 && - errno == EINTR) - continue; - } + term_restore(input); (void) sigaction(SIGALRM, &savealrm, NULL); (void) sigaction(SIGINT, &saveint, NULL); (void) sigaction(SIGHUP, &savehup, NULL); @@ -269,35 +208,64 @@ sudo_askpass(prompt) /* Get response from child (askpass) and restore SIGPIPE handler */ (void) close(pfd[1]); - pass = getln(pfd[0], buf, sizeof(buf)); + pass = getln(pfd[0], buf, sizeof(buf), 0); (void) close(pfd[0]); (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL); return(pass); } +extern int term_erase, term_kill; + static char * -getln(fd, buf, bufsiz) +getln(fd, buf, bufsiz, feedback) int fd; char *buf; size_t bufsiz; + int feedback; { + size_t left = bufsiz; ssize_t nr = -1; char *cp = buf; char c = '\0'; - if (bufsiz == 0) { + if (left == 0) { errno = EINVAL; return(NULL); /* sanity */ } - while (--bufsiz) { + while (--left) { nr = read(fd, &c, 1); if (nr != 1 || c == '\n' || c == '\r') break; + if (feedback) { + if (c == term_kill) { + while (cp > buf) { + (void) write(fd, "\b \b", 3); + --cp; + } + left = bufsiz; + continue; + } else if (c == term_erase) { + if (cp > buf) { + (void) write(fd, "\b \b", 3); + --cp; + left++; + } + continue; + } + (void) write(fd, "*", 1); + } *cp++ = c; } *cp = '\0'; + if (feedback) { + /* erase stars */ + while (cp > buf) { + (void) write(fd, "\b \b", 3); + --cp; + } + } return(nr == 1 ? buf : NULL); } diff --git a/toke.c b/toke.c index 0fd8ef9..a4bcb8e 100644 --- a/toke.c +++ b/toke.c @@ -3,7 +3,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /home/cvs/courtesan/sudo/toke.c,v 1.27 2008/11/24 00:42:20 millert Exp $ + * $Header: /home/cvs/courtesan/sudo/toke.c,v 1.36 2009/05/27 00:47:17 millert Exp $ */ #define FLEX_SCANNER @@ -288,69 +288,71 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 48 -#define YY_END_OF_BUFFER 49 -static yyconst short int yy_accept[534] = +#define YY_NUM_RULES 50 +#define YY_END_OF_BUFFER 51 +static yyconst short int yy_accept[554] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 49, 36, 44, 43, 42, 47, 36, 37, - 38, 36, 39, 36, 36, 36, 36, 41, 40, 47, - 32, 32, 32, 32, 32, 32, 47, 36, 36, 44, - 47, 32, 32, 32, 32, 32, 1, 47, 36, 36, - 16, 15, 16, 15, 15, 47, 47, 47, 2, 8, - 7, 8, 3, 8, 4, 47, 12, 12, 12, 10, - 11, 36, 0, 44, 42, 0, 46, 0, 36, 27, - 0, 26, 0, 35, 35, 0, 36, 36, 0, 36, - 36, 36, 36, 0, 30, 32, 32, 32, 32, 32, - - 32, 36, 45, 36, 44, 0, 0, 0, 0, 0, - 0, 36, 36, 36, 36, 36, 1, 33, 33, 0, - 36, 16, 16, 14, 13, 14, 0, 2, 8, 0, - 5, 6, 8, 8, 12, 0, 12, 12, 0, 9, - 0, 0, 36, 36, 36, 36, 36, 0, 0, 30, - 30, 32, 32, 32, 32, 32, 32, 32, 36, 0, - 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, - 0, 36, 9, 36, 36, 36, 36, 36, 36, 0, - 31, 31, 31, 0, 0, 30, 30, 30, 30, 30, - 30, 30, 32, 32, 32, 32, 32, 32, 32, 36, - - 0, 0, 0, 0, 0, 0, 36, 36, 36, 36, - 36, 36, 36, 0, 0, 31, 31, 31, 0, 30, - 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 0, 23, 32, 32, 32, 32, 32, - 36, 0, 0, 0, 0, 36, 36, 36, 36, 36, - 36, 36, 36, 0, 31, 0, 30, 30, 30, 0, - 0, 0, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 32, 32, 32, 32, 32, - 36, 0, 0, 0, 36, 36, 36, 28, 28, 28, - 0, 0, 30, 30, 30, 30, 30, 30, 30, 0, - - 0, 0, 0, 0, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 0, 22, - 32, 32, 0, 21, 0, 24, 36, 0, 0, 0, - 36, 36, 36, 36, 28, 28, 28, 28, 0, 30, - 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 0, 0, 0, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 32, 32, - 34, 0, 0, 0, 36, 18, 33, 36, 29, 29, - 29, 30, 0, 0, 0, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, - - 0, 0, 0, 30, 30, 30, 30, 30, 30, 30, - 30, 0, 20, 0, 25, 0, 18, 0, 36, 0, - 36, 36, 36, 29, 29, 29, 29, 29, 0, 0, - 0, 0, 0, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 0, 0, 19, 18, 0, 18, 0, - 36, 36, 36, 29, 29, 0, 0, 0, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 19, 0, 17, 36, - 36, 36, 36, 36, 0, 0, 0, 0, 0, 30, - - 30, 30, 30, 30, 30, 30, 30, 36, 36, 36, - 30, 30, 30, 30, 30, 30, 36, 36, 36, 36, - 36, 30, 30, 30, 30, 30, 28, 28, 28, 28, - 28, 28, 0 + 0, 0, 51, 38, 46, 45, 44, 38, 49, 38, + 39, 40, 38, 41, 38, 38, 38, 38, 43, 42, + 49, 33, 33, 33, 33, 33, 33, 49, 38, 38, + 46, 49, 33, 33, 33, 33, 33, 1, 49, 38, + 38, 16, 15, 16, 15, 15, 49, 49, 49, 2, + 8, 7, 8, 3, 8, 4, 49, 12, 12, 12, + 10, 11, 38, 0, 46, 44, 38, 0, 0, 0, + 48, 0, 38, 28, 0, 0, 27, 0, 36, 36, + 0, 38, 38, 0, 38, 38, 38, 38, 0, 31, + + 33, 33, 33, 33, 33, 33, 38, 47, 38, 46, + 0, 0, 0, 0, 0, 0, 38, 38, 38, 38, + 38, 1, 0, 34, 34, 0, 38, 16, 16, 14, + 13, 14, 0, 0, 2, 8, 0, 5, 6, 8, + 8, 12, 0, 12, 12, 0, 9, 37, 37, 0, + 0, 28, 0, 0, 38, 38, 38, 38, 38, 0, + 0, 31, 31, 33, 33, 33, 33, 33, 33, 33, + 38, 0, 0, 0, 0, 0, 0, 38, 38, 38, + 38, 38, 0, 38, 9, 0, 38, 38, 38, 38, + 38, 38, 0, 32, 32, 32, 0, 0, 31, 31, + + 31, 31, 31, 31, 31, 33, 33, 33, 33, 33, + 33, 33, 38, 0, 0, 0, 0, 0, 0, 38, + 38, 38, 38, 38, 38, 38, 0, 0, 32, 32, + 32, 0, 31, 31, 0, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 0, 24, 33, 33, + 33, 33, 33, 38, 0, 0, 0, 0, 38, 38, + 38, 38, 38, 38, 38, 38, 0, 32, 0, 31, + 31, 31, 0, 0, 0, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 33, 33, + 33, 33, 33, 38, 0, 0, 0, 38, 38, 38, + + 29, 29, 29, 0, 0, 31, 31, 31, 31, 31, + 31, 31, 0, 0, 0, 0, 0, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 0, 23, 33, 33, 0, 22, 0, 25, 38, + 0, 0, 0, 38, 38, 38, 38, 29, 29, 29, + 29, 0, 31, 0, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 0, 0, 0, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 33, 33, 35, 0, 0, 0, 38, 19, 34, + 38, 30, 30, 30, 31, 0, 0, 0, 31, 31, + + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 0, 0, 0, 0, 0, 31, 31, 31, 31, + 31, 31, 31, 31, 0, 21, 0, 26, 0, 19, + 0, 0, 38, 0, 38, 38, 38, 30, 30, 30, + 30, 30, 0, 0, 0, 0, 0, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, + 20, 19, 0, 19, 0, 38, 38, 38, 30, 30, + 0, 0, 0, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + + 31, 20, 0, 17, 0, 38, 38, 38, 38, 38, + 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, + 31, 31, 31, 0, 38, 38, 38, 31, 31, 31, + 31, 31, 31, 0, 38, 38, 38, 38, 38, 31, + 31, 31, 31, 31, 0, 18, 29, 29, 29, 29, + 29, 29, 0 } ; static yyconst int yy_ec[256] = @@ -396,527 +398,545 @@ static yyconst int yy_meta[63] = 12, 12 } ; -static yyconst short int yy_base[594] = +static yyconst short int yy_base[620] = { 0, 0, 61, 62, 63, 69, 84, 128, 189, 250, 294, - 80, 101, 2227, 2181, 2223, 3353, 2220, 337, 2164, 3353, - 3353, 2154, 3353, 107, 347, 119, 137, 2172, 3353, 3353, - 399, 2143, 446, 2141, 2139, 2098, 497, 145, 35, 167, - 521, 2073, 2042, 2034, 2019, 2010, 2065, 193, 256, 55, - 0, 3353, 2062, 0, 3353, 264, 573, 110, 0, 2020, - 3353, 73, 3353, 76, 3353, 117, 2016, 105, 106, 3353, - 142, 2014, 306, 2056, 2053, 2051, 3353, 201, 209, 1993, - 506, 1990, 543, 276, 1989, 554, 306, 581, 2002, 2002, - 325, 364, 317, 1982, 55, 618, 0, 1971, 240, 1963, - - 1961, 125, 3353, 98, 523, 1936, 1923, 1913, 1908, 1909, - 146, 115, 219, 29, 212, 149, 1966, 481, 1922, 649, - 154, 0, 1954, 256, 3353, 3353, 284, 0, 1897, 674, - 3353, 3353, 1875, 484, 1848, 1885, 271, 307, 288, 1860, - 1858, 676, 688, 720, 752, 784, 1846, 1835, 821, 268, - 859, 896, 1820, 1799, 1814, 1809, 1786, 1792, 236, 1765, - 1754, 1745, 1726, 1698, 300, 157, 1701, 259, 79, 329, - 691, 344, 1711, 598, 348, 935, 967, 703, 366, 1688, - 1687, 733, 455, 1686, 1670, 464, 709, 999, 760, 606, - 1037, 770, 1669, 401, 1643, 1635, 1632, 1613, 1620, 356, - - 1604, 1578, 1563, 1575, 1547, 369, 435, 503, 233, 466, - 1076, 1108, 1140, 1581, 1580, 801, 1565, 1563, 1562, 1545, - 467, 838, 557, 876, 559, 1172, 0, 915, 1183, 943, - 742, 1221, 953, 511, 3353, 1538, 1515, 1521, 1521, 1509, - 483, 1477, 1460, 1461, 543, 363, 21, 532, 979, 505, - 1260, 1292, 989, 1496, 1479, 1468, 1467, 1322, 468, 1019, - 1056, 1086, 630, 648, 670, 1094, 926, 1361, 0, 1118, - 1372, 1127, 846, 1410, 1150, 582, 1447, 1438, 583, 640, - 636, 1409, 1381, 641, 632, 459, 638, 1448, 1479, 1510, - 1411, 1393, 1381, 1158, 1542, 1200, 884, 1579, 1240, 1268, - - 1385, 1278, 1302, 1312, 674, 720, 1067, 1251, 1339, 1383, - 1618, 0, 1394, 1629, 1427, 1208, 1667, 1458, 694, 3353, - 1318, 1306, 743, 3353, 806, 3353, 749, 1292, 1274, 605, - 923, 751, 876, 1466, 784, 1705, 1736, 1489, 1280, 1243, - 1496, 771, 1519, 968, 1768, 0, 565, 1779, 1527, 1347, - 1816, 1561, 1598, 1648, 1686, 1047, 1231, 1677, 1715, 1715, - 1746, 1855, 0, 1748, 1866, 1724, 1435, 1757, 824, 918, - 1219, 1194, 1187, 657, 667, 1895, 1165, 1927, 1959, 1991, - 2023, 1160, 1798, 1835, 1886, 1158, 980, 1127, 1907, 1141, - 2055, 0, 724, 2066, 1915, 1935, 2103, 1943, 1967, 1069, - - 1977, 2001, 2011, 1278, 1312, 1877, 813, 832, 2142, 0, - 862, 1099, 3353, 1116, 3353, 1033, 2029, 976, 878, 1019, - 1000, 2083, 1018, 2152, 2184, 2216, 2248, 2046, 2120, 997, - 2162, 2172, 2194, 969, 898, 1293, 1392, 2200, 1543, 2280, - 0, 1003, 2291, 2224, 2031, 2328, 2234, 2257, 2266, 2309, - 1561, 871, 1029, 749, 761, 668, 650, 2359, 626, 2384, - 2397, 2429, 2461, 2381, 1894, 2411, 2439, 2449, 628, 546, - 1599, 1649, 2469, 1780, 2493, 0, 1097, 2504, 2477, 2091, - 2523, 544, 2542, 2551, 2420, 521, 3353, 513, 3353, 2559, - 1138, 2591, 2623, 2570, 2576, 488, 2602, 2612, 2633, 460, - - 381, 1799, 359, 303, 2641, 0, 1186, 2655, 2687, 2719, - 2663, 2671, 2695, 289, 0, 182, 2703, 1289, 2751, 2783, - 2733, 3353, 2739, 2763, 2128, 3353, 2771, 2791, 2801, 126, - 2821, 2813, 3353, 2866, 2879, 2892, 2905, 2918, 2931, 2944, - 2957, 2970, 2975, 2988, 3001, 3003, 3016, 3029, 3042, 3055, - 3068, 3073, 3079, 3092, 3097, 3103, 3108, 3113, 3118, 3124, - 3129, 3134, 3139, 3145, 3152, 3157, 3162, 3167, 3173, 3180, - 3185, 3190, 3196, 3203, 3208, 3215, 3221, 3228, 3233, 3240, - 3246, 3253, 3266, 3279, 3284, 3291, 3297, 3310, 3315, 3322, - 3327, 3334, 3339 - + 80, 101, 2349, 2303, 2345, 3488, 2316, 338, 381, 52, + 3488, 3488, 2272, 3488, 107, 391, 119, 137, 2292, 3488, + 3488, 443, 2271, 490, 2270, 2260, 2253, 541, 145, 55, + 167, 565, 2228, 2232, 2224, 2219, 2206, 2254, 193, 256, + 56, 0, 3488, 2249, 0, 3488, 264, 617, 77, 0, + 2199, 3488, 82, 3488, 99, 3488, 110, 2189, 126, 106, + 3488, 145, 2179, 306, 2185, 2182, 639, 2145, 2144, 2135, + 3488, 201, 209, 74, 2082, 347, 2079, 550, 276, 2078, + 587, 410, 669, 2098, 2104, 306, 358, 317, 2092, 179, + + 706, 0, 2083, 240, 2075, 2071, 389, 3488, 76, 355, + 2039, 2041, 2033, 2021, 2000, 63, 115, 219, 29, 212, + 98, 2056, 507, 361, 1986, 598, 154, 0, 2024, 256, + 3488, 3488, 636, 284, 0, 1982, 567, 3488, 3488, 1981, + 532, 1979, 1994, 271, 300, 288, 1975, 1905, 3488, 1944, + 1916, 1873, 669, 603, 745, 777, 809, 841, 1902, 1876, + 878, 268, 916, 953, 1869, 1854, 1854, 1849, 1841, 1831, + 236, 1805, 1788, 1746, 1748, 1719, 317, 157, 1722, 307, + 266, 258, 777, 296, 1766, 1764, 686, 402, 992, 1024, + 725, 337, 1727, 1726, 787, 499, 1708, 1707, 343, 755, + + 1056, 796, 694, 1094, 819, 1705, 393, 1681, 1673, 1671, + 1639, 1646, 373, 1629, 1616, 1601, 1614, 1586, 543, 400, + 556, 233, 506, 1133, 1165, 1197, 1620, 1619, 827, 1619, + 1602, 1601, 1590, 540, 858, 546, 895, 602, 1229, 0, + 935, 1240, 970, 731, 1278, 1002, 601, 3488, 1581, 1571, + 1577, 1577, 1537, 486, 1532, 1515, 1470, 387, 343, 380, + 616, 1010, 423, 1317, 1349, 1044, 1470, 1469, 1451, 1450, + 1379, 645, 1076, 1113, 1143, 652, 983, 1035, 1151, 1042, + 1418, 0, 1175, 1429, 1184, 866, 1467, 1207, 644, 1430, + 1436, 648, 672, 625, 1428, 1400, 680, 576, 487, 715, + + 1505, 1536, 1567, 1430, 1382, 1381, 1215, 1599, 1257, 903, + 1636, 1297, 1325, 1347, 1335, 1359, 1369, 841, 1024, 1067, + 1124, 1396, 1308, 1675, 0, 1448, 1686, 1484, 1265, 1724, + 1515, 955, 3488, 1329, 1282, 956, 3488, 975, 3488, 807, + 1266, 1244, 591, 1074, 569, 917, 1523, 155, 1762, 1793, + 1546, 1280, 1243, 1553, 768, 1576, 810, 1825, 0, 429, + 1836, 1584, 1404, 1873, 1618, 1655, 1705, 1743, 1288, 1335, + 1734, 1772, 1772, 1803, 1912, 0, 1805, 1923, 1781, 1492, + 1814, 993, 1156, 1221, 1211, 1181, 730, 635, 1952, 1194, + 1984, 2016, 2048, 2080, 1153, 1855, 1892, 1943, 1152, 1184, + + 1198, 1964, 1350, 2112, 0, 762, 2123, 1972, 1992, 2160, + 2000, 2024, 1126, 2034, 2058, 2068, 1369, 1609, 1934, 772, + 806, 2199, 0, 844, 1173, 3488, 1468, 3488, 1090, 2086, + 1389, 142, 991, 1076, 1075, 2140, 1038, 2209, 2241, 2273, + 2305, 2103, 2177, 1088, 2219, 2229, 2251, 1077, 1076, 1656, + 1706, 2257, 1837, 2337, 0, 881, 2348, 2281, 2088, 2385, + 2291, 2314, 2323, 2366, 1855, 981, 927, 934, 957, 902, + 898, 808, 2416, 743, 2441, 2454, 2486, 2518, 2438, 1951, + 2468, 2496, 2506, 757, 716, 1893, 2001, 2526, 2035, 2550, + 0, 1012, 2561, 2534, 2148, 2580, 647, 2599, 2608, 2477, + + 634, 3488, 629, 3488, 1051, 2616, 1195, 2648, 2680, 2627, + 2633, 594, 2659, 2669, 2690, 573, 566, 2049, 557, 549, + 2698, 0, 1045, 1545, 2712, 2744, 2776, 2720, 2728, 2752, + 509, 0, 455, 357, 2760, 1535, 2808, 2840, 2790, 3488, + 2796, 2820, 2185, 3488, 345, 3488, 2828, 2848, 2858, 25, + 2878, 2870, 3488, 2923, 2936, 2949, 2962, 2975, 2988, 3001, + 3014, 3027, 3040, 3045, 3058, 3071, 3073, 3086, 3099, 3112, + 3125, 3138, 3151, 3164, 3177, 3182, 3188, 3201, 3214, 3219, + 3225, 3230, 3235, 3240, 3246, 3251, 3256, 3261, 3267, 3274, + 3279, 3284, 3289, 3295, 3302, 3307, 3312, 3318, 3325, 3330, + + 3337, 3343, 3350, 3355, 3362, 3368, 3375, 3388, 3401, 3406, + 3413, 3419, 3432, 3437, 3444, 3449, 3456, 3461, 3474 } ; -static yyconst short int yy_def[594] = +static yyconst short int yy_def[620] = { 0, - 533, 1, 1, 1, 534, 534, 535, 535, 536, 536, - 537, 537, 533, 538, 533, 533, 533, 539, 540, 533, - 533, 541, 533, 542, 538, 25, 25, 543, 533, 533, - 533, 31, 31, 33, 33, 33, 538, 25, 538, 533, - 539, 31, 31, 33, 33, 33, 533, 533, 544, 538, - 545, 533, 545, 545, 533, 533, 539, 533, 546, 547, - 533, 547, 533, 547, 533, 548, 549, 549, 549, 533, - 533, 538, 538, 533, 533, 550, 533, 533, 533, 540, - 540, 541, 541, 542, 551, 538, 538, 25, 543, 88, - 88, 88, 88, 552, 553, 31, 33, 33, 33, 33, - - 33, 538, 533, 538, 533, 533, 533, 533, 533, 533, - 550, 538, 88, 538, 538, 538, 533, 544, 554, 538, - 538, 545, 545, 533, 533, 533, 533, 546, 547, 547, - 533, 533, 547, 547, 549, 533, 549, 549, 533, 533, - 550, 533, 538, 538, 538, 88, 146, 555, 533, 556, - 533, 31, 33, 33, 33, 33, 33, 33, 538, 533, - 533, 533, 533, 533, 550, 538, 146, 538, 538, 538, - 533, 538, 533, 538, 538, 538, 538, 538, 538, 557, - 558, 558, 182, 559, 558, 560, 151, 533, 188, 188, - 533, 188, 33, 33, 33, 33, 33, 33, 33, 538, - - 533, 533, 533, 533, 533, 550, 538, 538, 538, 538, - 538, 538, 538, 533, 561, 561, 216, 561, 562, 563, - 564, 533, 565, 191, 565, 565, 226, 565, 533, 229, - 229, 533, 229, 533, 533, 33, 33, 33, 33, 33, - 538, 533, 533, 533, 550, 538, 538, 538, 538, 538, - 538, 538, 538, 566, 566, 567, 568, 533, 533, 533, - 533, 533, 569, 569, 570, 232, 570, 570, 268, 570, - 533, 271, 271, 533, 271, 33, 33, 33, 33, 33, - 538, 533, 533, 550, 538, 538, 538, 538, 538, 538, - 533, 571, 572, 258, 533, 295, 295, 533, 295, 533, - - 533, 533, 533, 533, 533, 573, 573, 574, 274, 574, - 574, 311, 574, 533, 314, 314, 533, 314, 533, 533, - 33, 33, 533, 533, 533, 533, 538, 533, 533, 550, - 538, 538, 538, 538, 538, 538, 538, 538, 533, 575, - 533, 576, 298, 576, 576, 345, 345, 533, 348, 348, - 533, 348, 533, 533, 533, 533, 577, 577, 578, 317, - 578, 578, 362, 578, 533, 365, 365, 365, 33, 33, - 538, 533, 533, 550, 538, 538, 538, 538, 538, 538, - 538, 533, 533, 533, 533, 579, 579, 580, 351, 580, - 580, 391, 391, 533, 394, 394, 533, 394, 533, 533, - - 533, 533, 533, 533, 581, 581, 582, 582, 582, 409, - 409, 533, 533, 533, 533, 533, 533, 550, 538, 583, - 584, 538, 538, 538, 538, 538, 538, 538, 533, 533, - 533, 533, 533, 533, 585, 585, 586, 397, 586, 586, - 440, 440, 533, 443, 443, 533, 443, 533, 533, 533, - 533, 587, 587, 533, 588, 538, 583, 583, 584, 584, - 538, 538, 538, 538, 538, 533, 533, 533, 533, 589, - 589, 590, 446, 590, 590, 475, 475, 533, 478, 478, - 478, 533, 533, 533, 533, 533, 533, 588, 533, 538, - 538, 538, 538, 538, 533, 533, 533, 533, 533, 533, - - 591, 591, 592, 592, 592, 505, 505, 538, 538, 538, - 533, 533, 533, 533, 593, 593, 538, 538, 538, 538, - 538, 533, 533, 533, 533, 533, 538, 538, 538, 538, - 538, 538, 0, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533 - + 553, 1, 1, 1, 554, 554, 555, 555, 556, 556, + 557, 557, 553, 558, 553, 553, 553, 559, 560, 561, + 553, 553, 562, 553, 563, 558, 26, 26, 564, 553, + 553, 553, 32, 32, 34, 34, 34, 558, 26, 558, + 553, 560, 32, 32, 34, 34, 34, 553, 553, 565, + 558, 566, 553, 566, 566, 553, 553, 560, 553, 567, + 568, 553, 568, 553, 568, 553, 569, 570, 570, 570, + 553, 553, 558, 558, 553, 553, 559, 571, 559, 572, + 553, 573, 553, 561, 574, 561, 562, 562, 563, 575, + 558, 558, 26, 564, 93, 93, 93, 93, 576, 577, + + 32, 34, 34, 34, 34, 34, 558, 553, 558, 553, + 553, 553, 553, 553, 553, 572, 558, 93, 558, 558, + 558, 553, 553, 565, 578, 558, 558, 566, 566, 553, + 553, 553, 573, 553, 567, 568, 568, 553, 553, 568, + 568, 570, 553, 570, 570, 553, 553, 558, 553, 572, + 579, 574, 574, 553, 558, 558, 558, 93, 158, 580, + 553, 581, 553, 32, 34, 34, 34, 34, 34, 34, + 558, 553, 553, 553, 553, 553, 572, 558, 158, 558, + 558, 558, 553, 558, 553, 579, 558, 558, 558, 558, + 558, 558, 582, 583, 583, 195, 584, 583, 585, 163, + + 553, 201, 201, 553, 201, 34, 34, 34, 34, 34, + 34, 34, 558, 553, 553, 553, 553, 553, 572, 558, + 558, 558, 558, 558, 558, 558, 553, 586, 586, 229, + 586, 587, 588, 589, 553, 590, 204, 590, 590, 239, + 590, 553, 242, 242, 553, 242, 553, 553, 34, 34, + 34, 34, 34, 558, 553, 553, 553, 572, 558, 558, + 558, 558, 558, 558, 558, 558, 591, 591, 592, 593, + 553, 553, 553, 553, 553, 594, 594, 595, 245, 595, + 595, 281, 595, 553, 284, 284, 553, 284, 34, 34, + 34, 34, 34, 558, 553, 553, 572, 558, 558, 558, + + 558, 558, 558, 553, 596, 597, 271, 553, 308, 308, + 553, 308, 553, 553, 553, 553, 553, 553, 598, 598, + 599, 287, 599, 599, 324, 599, 553, 327, 327, 553, + 327, 553, 553, 34, 34, 553, 553, 553, 553, 558, + 553, 553, 572, 558, 558, 558, 558, 558, 558, 558, + 558, 553, 600, 553, 601, 311, 601, 601, 358, 358, + 553, 361, 361, 553, 361, 553, 553, 553, 553, 602, + 602, 603, 330, 603, 603, 375, 603, 553, 378, 378, + 378, 34, 34, 558, 553, 553, 572, 558, 558, 558, + 558, 558, 558, 558, 553, 553, 553, 553, 604, 604, + + 605, 364, 605, 605, 404, 404, 553, 407, 407, 553, + 407, 553, 553, 553, 553, 553, 553, 606, 606, 607, + 607, 607, 422, 422, 553, 553, 553, 553, 553, 553, + 572, 572, 558, 608, 609, 558, 558, 558, 558, 558, + 558, 558, 553, 553, 553, 553, 553, 553, 610, 610, + 611, 410, 611, 611, 454, 454, 553, 457, 457, 553, + 457, 553, 553, 553, 553, 612, 612, 553, 613, 572, + 558, 608, 608, 609, 609, 558, 558, 558, 558, 558, + 553, 553, 553, 553, 614, 614, 615, 460, 615, 615, + 490, 490, 553, 493, 493, 493, 553, 553, 553, 553, + + 553, 553, 613, 553, 572, 558, 558, 558, 558, 558, + 553, 553, 553, 553, 553, 553, 616, 616, 617, 617, + 617, 521, 521, 572, 558, 558, 558, 553, 553, 553, + 553, 618, 618, 619, 558, 558, 558, 558, 558, 553, + 553, 553, 553, 553, 619, 553, 558, 558, 558, 558, + 558, 558, 0, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553 } ; -static yyconst short int yy_nxt[3416] = +static yyconst short int yy_nxt[3551] = { 0, - 14, 15, 16, 17, 14, 18, 19, 20, 21, 14, - 22, 23, 14, 14, 24, 25, 26, 27, 25, 25, - 25, 25, 25, 28, 29, 30, 14, 31, 31, 31, - 31, 32, 33, 33, 34, 33, 35, 33, 36, 33, - 33, 33, 33, 33, 37, 14, 38, 38, 38, 38, - 38, 38, 14, 14, 14, 14, 14, 14, 14, 39, - 14, 14, 40, 47, 47, 73, 41, 48, 48, 149, - 15, 52, 53, 73, 54, 286, 49, 49, 151, 73, - 55, 68, 16, 69, 70, 15, 52, 53, 168, 54, - 42, 43, 55, 54, 44, 55, 104, 131, 45, 73, - - 132, 46, 68, 16, 69, 70, 137, 55, 54, 138, - 85, 127, 103, 56, 85, 85, 121, 130, 134, 103, - 130, 50, 50, 73, 71, 209, 127, 103, 56, 15, - 16, 17, 85, 57, 91, 91, 91, 91, 91, 91, - 91, 91, 73, 139, 140, 71, 135, 159, 77, 136, - 136, 86, 92, 92, 92, 92, 92, 93, 72, 73, - 90, 90, 90, 90, 90, 90, 90, 90, 105, 73, - 73, 166, 58, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 15, 16, 17, 73, 57, 341, 106, 107, 73, 170, - - 108, 73, 165, 172, 109, 78, 207, 110, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 72, 58, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 15, 16, 17, 61, 57, 73, 127, 103, 119, - 62, 63, 64, 119, 119, 124, 103, 125, 169, 126, - 167, 154, 137, 125, 65, 126, 155, 73, 156, 85, - 73, 119, 149, 85, 85, 127, 103, 126, 126, 139, - 140, 187, 207, 200, 66, 15, 16, 17, 61, 57, - - 120, 85, 77, 73, 62, 63, 64, 72, 126, 72, - 138, 72, 473, 72, 72, 136, 533, 72, 65, 207, - 86, 143, 144, 145, 143, 143, 143, 143, 143, 72, - 72, 72, 147, 147, 147, 147, 147, 147, 66, 77, - 147, 147, 147, 147, 147, 147, 147, 147, 206, 78, - 73, 136, 79, 79, 79, 79, 79, 79, 79, 79, - 87, 174, 88, 88, 88, 88, 88, 88, 88, 88, - 89, 77, 341, 73, 90, 90, 90, 90, 90, 147, - 147, 147, 147, 147, 147, 147, 147, 207, 73, 89, - 285, 73, 73, 90, 90, 90, 90, 90, 90, 72, - - 73, 210, 234, 72, 473, 72, 241, 73, 72, 72, - 73, 72, 72, 72, 96, 96, 96, 96, 96, 96, - 96, 96, 89, 245, 235, 72, 96, 96, 96, 96, - 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 73, 97, 90, 90, 90, 90, 90, - 90, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 97, 97, 97, 97, 97, 97, 97, 97, 533, - 218, 218, 218, 97, 97, 97, 97, 97, 149, 73, - 246, 149, 149, 438, 119, 127, 103, 187, 119, 119, - 187, 187, 72, 72, 72, 72, 72, 72, 102, 103, - - 72, 495, 72, 73, 72, 72, 119, 80, 72, 80, - 73, 80, 234, 80, 80, 489, 248, 80, 249, 332, - 72, 72, 72, 77, 105, 120, 89, 73, 130, 80, - 80, 80, 281, 78, 235, 149, 79, 79, 79, 79, - 79, 79, 79, 79, 82, 77, 82, 73, 82, 73, - 82, 82, 106, 107, 82, 84, 108, 72, 149, 84, - 109, 72, 72, 110, 247, 84, 82, 82, 82, 438, - 222, 149, 533, 149, 111, 77, 73, 84, 84, 72, - 224, 287, 224, 319, 323, 533, 386, 386, 533, 533, - 533, 533, 533, 533, 533, 533, 146, 146, 146, 146, - - 146, 146, 146, 146, 284, 320, 324, 77, 146, 146, - 146, 146, 146, 211, 212, 213, 211, 211, 211, 211, - 211, 227, 227, 227, 227, 227, 228, 146, 146, 146, - 146, 146, 146, 152, 152, 152, 152, 152, 152, 152, - 152, 325, 73, 77, 149, 152, 152, 152, 152, 152, - 118, 389, 72, 224, 118, 374, 72, 72, 418, 77, - 118, 222, 149, 326, 146, 146, 146, 146, 146, 146, - 460, 224, 118, 118, 72, 129, 73, 85, 129, 129, - 73, 85, 73, 222, 149, 129, 331, 85, 149, 327, - 330, 333, 119, 266, 458, 319, 119, 224, 129, 85, - - 85, 174, 119, 175, 175, 175, 175, 175, 175, 175, - 175, 73, 73, 419, 119, 119, 174, 320, 175, 175, - 175, 175, 175, 175, 192, 192, 192, 192, 192, 192, - 192, 192, 73, 174, 149, 176, 176, 176, 176, 176, - 176, 176, 176, 266, 323, 435, 435, 73, 216, 216, - 217, 218, 218, 218, 218, 218, 184, 269, 269, 269, - 269, 269, 270, 489, 73, 174, 324, 177, 177, 177, - 177, 177, 178, 175, 175, 226, 226, 226, 226, 226, - 226, 226, 226, 533, 341, 225, 225, 225, 225, 225, - 225, 225, 225, 73, 343, 73, 73, 72, 334, 179, - - 179, 179, 179, 179, 179, 179, 179, 325, 487, 371, - 376, 179, 179, 179, 179, 179, 255, 255, 255, 255, - 255, 255, 255, 255, 184, 412, 222, 149, 73, 326, - 179, 179, 179, 179, 179, 179, 181, 182, 183, 183, - 183, 183, 183, 183, 184, 533, 149, 413, 185, 185, - 185, 185, 185, 260, 261, 262, 260, 260, 260, 260, - 260, 312, 312, 312, 312, 312, 313, 185, 185, 185, - 185, 185, 185, 149, 188, 189, 190, 188, 188, 188, - 188, 188, 191, 452, 452, 149, 192, 192, 192, 192, - 192, 233, 233, 233, 233, 233, 233, 233, 233, 346, - - 346, 346, 346, 346, 347, 192, 192, 192, 192, 192, - 192, 193, 193, 193, 193, 193, 193, 193, 193, 414, - 73, 389, 73, 193, 193, 193, 193, 193, 222, 149, - 264, 264, 264, 264, 264, 264, 377, 456, 224, 533, - 149, 415, 179, 179, 179, 179, 179, 179, 174, 266, - 175, 175, 175, 175, 175, 175, 175, 175, 268, 268, - 268, 268, 268, 268, 268, 268, 533, 73, 267, 267, - 267, 267, 267, 267, 267, 267, 375, 418, 77, 73, - 174, 533, 175, 175, 175, 175, 175, 175, 175, 175, - 455, 343, 343, 341, 288, 289, 290, 288, 288, 288, - - 288, 288, 249, 343, 250, 250, 250, 250, 250, 250, - 429, 73, 222, 149, 223, 223, 223, 223, 223, 223, - 223, 223, 224, 73, 470, 470, 225, 225, 225, 225, - 225, 422, 300, 73, 301, 301, 301, 301, 301, 301, - 301, 301, 222, 149, 460, 225, 225, 225, 225, 225, - 225, 149, 229, 230, 231, 229, 229, 229, 229, 229, - 232, 149, 73, 458, 233, 233, 233, 233, 233, 300, - 266, 302, 302, 302, 302, 302, 302, 302, 302, 454, - 222, 149, 399, 233, 233, 233, 233, 233, 233, 249, - 266, 250, 250, 250, 250, 250, 250, 250, 250, 300, - - 412, 303, 303, 303, 303, 303, 304, 301, 301, 275, - 275, 275, 275, 275, 275, 275, 275, 414, 501, 501, - 73, 249, 413, 251, 251, 251, 251, 251, 251, 251, - 251, 222, 149, 307, 307, 307, 307, 307, 307, 415, - 341, 266, 311, 311, 311, 311, 311, 311, 311, 311, - 389, 490, 73, 249, 533, 252, 252, 252, 252, 252, - 253, 250, 250, 533, 389, 310, 310, 310, 310, 310, - 310, 310, 310, 299, 299, 299, 299, 299, 299, 299, - 299, 343, 73, 294, 73, 222, 149, 264, 264, 264, - 264, 264, 264, 264, 264, 224, 222, 149, 265, 265, - - 265, 265, 265, 265, 265, 265, 266, 515, 515, 73, - 267, 267, 267, 267, 267, 345, 345, 345, 345, 345, - 345, 345, 345, 363, 363, 363, 363, 363, 364, 267, - 267, 267, 267, 267, 267, 149, 271, 272, 273, 271, - 271, 271, 271, 271, 274, 149, 417, 416, 275, 275, - 275, 275, 275, 533, 309, 344, 344, 344, 344, 344, - 344, 344, 344, 73, 222, 149, 294, 275, 275, 275, - 275, 275, 275, 249, 309, 250, 250, 250, 250, 250, - 250, 250, 250, 353, 354, 355, 353, 353, 353, 353, - 353, 300, 149, 301, 301, 301, 301, 301, 301, 301, - - 301, 309, 517, 220, 73, 249, 341, 250, 250, 250, - 250, 250, 250, 250, 250, 300, 389, 301, 301, 301, - 301, 301, 301, 301, 301, 300, 149, 301, 301, 301, - 301, 301, 301, 73, 373, 360, 73, 295, 296, 297, - 295, 295, 295, 295, 295, 298, 372, 370, 369, 299, - 299, 299, 299, 299, 318, 318, 318, 318, 318, 318, - 318, 318, 392, 392, 392, 392, 392, 393, 299, 299, - 299, 299, 299, 299, 222, 149, 307, 307, 307, 307, - 307, 307, 307, 307, 266, 222, 149, 308, 308, 308, - 308, 308, 308, 308, 308, 309, 533, 149, 300, 310, - - 310, 310, 310, 310, 294, 341, 309, 222, 149, 358, - 358, 358, 358, 358, 358, 438, 220, 309, 310, 310, - 310, 310, 310, 310, 149, 314, 315, 316, 314, 314, - 314, 314, 314, 317, 184, 329, 328, 318, 318, 318, - 318, 318, 362, 362, 362, 362, 362, 362, 362, 362, - 410, 410, 410, 410, 410, 411, 318, 318, 318, 318, - 318, 318, 334, 335, 335, 335, 335, 335, 335, 335, - 335, 533, 322, 361, 361, 361, 361, 361, 361, 361, - 361, 378, 379, 380, 381, 378, 378, 378, 378, 321, - 294, 220, 73, 334, 336, 336, 336, 336, 336, 336, - - 336, 336, 184, 334, 335, 335, 335, 335, 335, 335, - 73, 383, 384, 385, 383, 383, 383, 383, 383, 184, - 242, 283, 282, 73, 334, 337, 337, 337, 337, 337, - 338, 335, 335, 73, 352, 352, 352, 352, 352, 352, - 352, 352, 391, 391, 391, 391, 391, 391, 391, 391, - 280, 279, 278, 277, 73, 341, 533, 342, 342, 342, - 342, 342, 342, 342, 342, 343, 438, 276, 258, 344, - 344, 344, 344, 344, 533, 149, 390, 390, 390, 390, - 390, 390, 390, 390, 360, 220, 184, 254, 344, 344, - 344, 344, 344, 344, 348, 349, 350, 348, 348, 348, - - 348, 348, 351, 184, 95, 242, 352, 352, 352, 352, - 352, 399, 341, 400, 400, 400, 400, 400, 400, 400, - 400, 244, 438, 242, 243, 352, 352, 352, 352, 352, - 352, 222, 149, 358, 358, 358, 358, 358, 358, 358, - 358, 309, 222, 149, 359, 359, 359, 359, 359, 359, - 359, 359, 360, 242, 240, 239, 361, 361, 361, 361, - 361, 399, 341, 401, 401, 401, 401, 401, 401, 401, - 401, 238, 473, 237, 236, 361, 361, 361, 361, 361, - 361, 149, 365, 366, 367, 365, 365, 365, 365, 365, - 222, 149, 89, 184, 368, 368, 368, 368, 368, 399, - - 309, 402, 402, 402, 402, 402, 403, 400, 400, 220, - 184, 95, 173, 368, 368, 368, 368, 368, 368, 334, - 335, 335, 335, 335, 335, 335, 335, 335, 222, 149, - 368, 368, 368, 368, 368, 368, 368, 368, 360, 409, - 409, 409, 409, 409, 409, 409, 409, 208, 205, 73, - 334, 335, 335, 335, 335, 335, 335, 335, 335, 533, - 149, 222, 149, 406, 406, 406, 406, 406, 406, 360, - 533, 360, 408, 408, 408, 408, 408, 408, 408, 408, - 73, 341, 204, 387, 387, 387, 387, 387, 387, 387, - 387, 343, 341, 533, 388, 388, 388, 388, 388, 388, - - 388, 388, 389, 473, 203, 202, 390, 390, 390, 390, - 390, 429, 341, 430, 430, 430, 430, 430, 430, 430, - 430, 201, 473, 199, 198, 390, 390, 390, 390, 390, - 390, 394, 395, 396, 394, 394, 394, 394, 394, 397, - 197, 196, 195, 398, 398, 398, 398, 398, 429, 194, - 431, 431, 431, 431, 431, 431, 431, 431, 95, 87, - 77, 173, 398, 398, 398, 398, 398, 398, 222, 149, - 406, 406, 406, 406, 406, 406, 406, 406, 360, 222, - 149, 407, 407, 407, 407, 407, 407, 407, 407, 135, - 222, 149, 136, 408, 408, 408, 408, 408, 420, 429, - - 360, 432, 432, 432, 432, 432, 433, 430, 430, 465, - 465, 465, 408, 408, 408, 408, 408, 408, 420, 130, - 420, 421, 398, 398, 398, 398, 398, 398, 398, 398, - 440, 440, 440, 440, 440, 440, 440, 440, 73, 73, - 422, 130, 423, 423, 423, 423, 423, 423, 423, 423, - 441, 441, 441, 441, 441, 442, 533, 123, 439, 439, - 439, 439, 439, 439, 439, 439, 171, 117, 164, 163, - 162, 73, 422, 161, 424, 424, 424, 424, 424, 424, - 424, 424, 448, 449, 450, 448, 448, 448, 448, 448, - 399, 160, 400, 400, 400, 400, 400, 400, 400, 400, - - 158, 157, 153, 73, 422, 95, 425, 425, 425, 425, - 425, 426, 427, 427, 399, 72, 400, 400, 400, 400, - 400, 400, 400, 400, 399, 95, 400, 400, 400, 400, - 400, 400, 420, 142, 83, 73, 422, 81, 428, 428, - 428, 423, 423, 423, 423, 423, 476, 476, 476, 476, - 476, 477, 420, 77, 420, 420, 75, 74, 73, 422, - 136, 465, 465, 465, 130, 123, 117, 73, 341, 116, - 436, 436, 436, 436, 436, 436, 436, 436, 389, 341, - 115, 437, 437, 437, 437, 437, 437, 437, 437, 438, - 73, 114, 113, 439, 439, 439, 439, 439, 461, 462, - - 463, 461, 461, 461, 461, 461, 506, 506, 506, 506, - 506, 507, 439, 439, 439, 439, 439, 439, 443, 444, - 445, 443, 443, 443, 443, 443, 446, 73, 112, 101, - 447, 447, 447, 447, 447, 466, 467, 468, 466, 466, - 466, 466, 466, 522, 522, 522, 522, 522, 522, 447, - 447, 447, 447, 447, 447, 222, 149, 453, 453, 453, - 453, 453, 453, 453, 453, 422, 100, 427, 427, 427, - 427, 427, 427, 427, 427, 429, 99, 430, 430, 430, - 430, 430, 430, 430, 430, 429, 98, 430, 430, 430, - 430, 430, 430, 430, 430, 95, 73, 422, 83, 427, - - 427, 427, 427, 427, 427, 427, 427, 429, 81, 430, - 430, 430, 430, 430, 430, 447, 447, 447, 447, 447, - 447, 447, 447, 75, 74, 73, 533, 533, 73, 422, - 533, 427, 427, 427, 427, 427, 427, 464, 464, 475, - 475, 475, 475, 475, 475, 475, 475, 533, 533, 474, - 474, 474, 474, 474, 474, 474, 474, 533, 533, 533, - 73, 422, 533, 464, 464, 464, 464, 464, 464, 464, - 464, 149, 482, 482, 482, 482, 482, 482, 482, 482, - 149, 483, 483, 483, 483, 483, 483, 483, 483, 533, - 533, 533, 73, 341, 533, 471, 471, 471, 471, 471, - - 471, 471, 471, 438, 341, 533, 472, 472, 472, 472, - 472, 472, 472, 472, 473, 533, 533, 533, 474, 474, - 474, 474, 474, 149, 484, 484, 484, 484, 484, 485, - 482, 482, 533, 533, 533, 533, 533, 474, 474, 474, - 474, 474, 474, 478, 479, 480, 478, 478, 478, 478, - 478, 533, 533, 533, 533, 481, 481, 481, 481, 481, - 457, 533, 457, 533, 457, 533, 457, 457, 533, 533, - 457, 533, 533, 533, 481, 481, 481, 481, 481, 481, - 533, 533, 457, 457, 457, 459, 533, 459, 533, 459, - 533, 459, 459, 533, 533, 459, 464, 464, 464, 464, - - 464, 464, 464, 464, 533, 533, 533, 459, 459, 459, - 490, 533, 491, 491, 491, 491, 491, 491, 491, 491, - 533, 533, 533, 533, 495, 73, 496, 496, 496, 496, - 496, 496, 496, 496, 149, 482, 482, 482, 482, 482, - 482, 73, 490, 533, 492, 492, 492, 492, 492, 492, - 492, 492, 495, 533, 497, 497, 497, 497, 497, 497, - 497, 497, 495, 533, 498, 498, 498, 498, 498, 499, - 496, 496, 533, 73, 490, 533, 493, 493, 493, 493, - 493, 494, 491, 491, 481, 481, 481, 481, 481, 481, - 481, 481, 505, 505, 505, 505, 505, 505, 505, 505, - - 533, 533, 533, 533, 533, 73, 341, 533, 502, 502, - 502, 502, 502, 502, 502, 502, 473, 341, 533, 503, - 503, 503, 503, 503, 503, 503, 503, 533, 533, 533, - 533, 504, 504, 504, 504, 504, 533, 533, 504, 504, - 504, 504, 504, 504, 504, 504, 533, 533, 533, 533, - 504, 504, 504, 504, 504, 504, 149, 482, 482, 482, - 482, 482, 482, 482, 482, 149, 482, 482, 482, 482, - 482, 482, 482, 482, 508, 509, 510, 508, 508, 508, - 508, 508, 533, 490, 533, 491, 491, 491, 491, 491, - 491, 511, 512, 513, 511, 511, 511, 511, 511, 533, - - 533, 533, 533, 73, 490, 533, 491, 491, 491, 491, - 491, 491, 491, 491, 73, 495, 533, 496, 496, 496, - 496, 496, 496, 496, 496, 495, 533, 496, 496, 496, - 496, 496, 496, 496, 496, 73, 490, 533, 491, 491, - 491, 491, 491, 491, 491, 491, 495, 533, 496, 496, - 496, 496, 496, 496, 341, 533, 516, 516, 516, 516, - 516, 516, 516, 516, 533, 533, 533, 73, 517, 533, - 518, 518, 518, 518, 518, 518, 518, 518, 522, 522, - 522, 522, 522, 522, 522, 522, 523, 523, 523, 523, - 523, 523, 523, 523, 533, 533, 533, 533, 533, 73, - - 517, 533, 519, 519, 519, 519, 519, 519, 519, 519, - 524, 524, 524, 524, 524, 525, 522, 522, 527, 528, - 529, 527, 527, 527, 527, 527, 533, 533, 533, 533, - 533, 73, 517, 533, 520, 520, 520, 520, 520, 521, - 518, 518, 533, 533, 533, 533, 517, 73, 518, 518, - 518, 518, 518, 518, 522, 522, 522, 522, 522, 522, - 522, 522, 533, 73, 517, 533, 518, 518, 518, 518, - 518, 518, 518, 518, 533, 533, 533, 73, 522, 522, - 522, 522, 522, 522, 522, 522, 530, 530, 530, 530, - 530, 530, 530, 530, 533, 73, 517, 533, 518, 518, - - 518, 518, 518, 518, 518, 518, 527, 527, 527, 527, - 527, 527, 527, 527, 533, 73, 531, 531, 531, 531, - 531, 532, 530, 530, 533, 533, 533, 73, 530, 530, - 530, 530, 530, 530, 533, 73, 530, 530, 530, 530, - 530, 530, 530, 530, 533, 73, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 73, 533, 533, - 533, 533, 533, 533, 533, 73, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 60, 60, 60, 60, 60, 60, 60, 60, - - 60, 60, 60, 60, 60, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 67, 72, 533, - 533, 533, 72, 533, 72, 72, 72, 533, 72, 72, - 72, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 80, 533, 533, 533, 80, 533, - 80, 80, 80, 533, 80, 80, 80, 82, 533, 533, - 533, 82, 533, 82, 82, 82, 533, 82, 82, 82, - 84, 533, 533, 84, 84, 533, 84, 84, 84, 533, - 84, 84, 84, 94, 94, 533, 533, 94, 118, 533, - 533, 118, 118, 533, 118, 118, 118, 533, 118, 118, - - 118, 122, 533, 533, 122, 122, 122, 122, 122, 122, - 533, 533, 122, 122, 128, 128, 129, 533, 533, 129, - 533, 533, 129, 129, 129, 129, 129, 129, 129, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 135, 135, 533, 135, 533, 135, 135, 135, - 135, 135, 135, 135, 135, 141, 141, 141, 141, 141, - 141, 141, 141, 141, 141, 141, 141, 141, 85, 533, - 533, 85, 85, 533, 85, 85, 85, 533, 85, 85, - 85, 148, 148, 533, 533, 148, 150, 150, 150, 533, - 533, 150, 119, 533, 533, 119, 119, 533, 119, 119, - - 119, 533, 119, 119, 119, 180, 180, 533, 533, 180, - 186, 186, 186, 533, 533, 186, 214, 214, 533, 533, - 214, 215, 215, 533, 533, 215, 219, 219, 533, 533, - 219, 221, 221, 221, 533, 533, 221, 254, 254, 533, - 533, 254, 256, 256, 533, 533, 256, 257, 257, 533, - 533, 257, 259, 259, 259, 533, 533, 259, 263, 263, - 263, 263, 533, 533, 263, 291, 291, 533, 533, 291, - 292, 292, 533, 533, 292, 293, 293, 533, 533, 293, - 305, 305, 305, 533, 533, 305, 306, 306, 306, 306, - 533, 533, 306, 339, 339, 533, 533, 339, 340, 340, - - 533, 533, 340, 356, 356, 356, 533, 533, 356, 357, - 357, 357, 357, 533, 533, 357, 382, 382, 533, 533, - 382, 386, 533, 386, 386, 533, 533, 386, 404, 404, - 404, 533, 533, 404, 405, 405, 405, 405, 533, 533, - 405, 434, 434, 533, 533, 434, 435, 533, 435, 435, - 533, 533, 435, 451, 451, 451, 533, 533, 451, 452, - 452, 452, 533, 533, 533, 452, 457, 533, 533, 533, - 457, 533, 457, 457, 457, 533, 457, 457, 457, 459, - 533, 533, 533, 459, 533, 459, 459, 459, 533, 459, - 459, 459, 469, 469, 533, 533, 469, 470, 533, 470, - - 470, 533, 533, 470, 486, 486, 533, 533, 533, 486, - 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, - 488, 488, 488, 500, 500, 533, 533, 500, 501, 533, - 501, 501, 533, 533, 501, 514, 514, 533, 533, 514, - 515, 533, 515, 533, 533, 533, 515, 526, 533, 533, - 533, 526, 13, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533 + 14, 15, 16, 17, 18, 19, 20, 21, 22, 14, + 23, 24, 14, 14, 25, 26, 27, 28, 26, 26, + 26, 26, 26, 29, 30, 31, 14, 32, 32, 32, + 32, 33, 34, 34, 35, 34, 36, 34, 37, 34, + 34, 34, 34, 34, 38, 14, 39, 39, 39, 39, + 39, 39, 14, 14, 14, 14, 14, 14, 14, 40, + 14, 14, 41, 48, 48, 81, 42, 49, 49, 74, + 15, 53, 54, 74, 55, 85, 50, 50, 134, 108, + 56, 69, 16, 70, 71, 15, 53, 54, 180, 55, + 43, 44, 56, 55, 45, 56, 86, 553, 46, 74, + + 74, 47, 69, 16, 70, 71, 138, 56, 55, 145, + 90, 141, 108, 57, 90, 90, 109, 127, 86, 177, + 74, 51, 51, 139, 72, 171, 137, 144, 57, 15, + 16, 17, 90, 58, 96, 96, 96, 96, 96, 96, + 96, 96, 74, 137, 81, 72, 146, 147, 182, 142, + 143, 91, 97, 97, 97, 97, 97, 98, 73, 74, + 95, 95, 95, 95, 95, 95, 95, 95, 110, 347, + 143, 178, 59, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 15, 16, 17, 161, 58, 470, 111, 112, 74, 74, + + 113, 74, 163, 184, 114, 123, 220, 115, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 73, 59, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 15, 16, 17, 62, 58, 74, 134, 108, 125, + 63, 64, 65, 125, 125, 130, 108, 131, 181, 132, + 179, 166, 144, 131, 66, 132, 167, 74, 168, 90, + 74, 125, 161, 90, 90, 134, 108, 132, 132, 146, + 147, 200, 220, 213, 67, 15, 16, 17, 62, 58, + + 126, 90, 74, 145, 63, 64, 65, 73, 132, 73, + 74, 73, 222, 73, 73, 143, 220, 73, 66, 81, + 91, 159, 159, 159, 159, 159, 159, 159, 159, 73, + 73, 73, 159, 159, 159, 159, 159, 159, 67, 78, + 74, 78, 73, 78, 143, 78, 78, 546, 84, 78, + 84, 74, 84, 223, 84, 84, 110, 161, 84, 546, + 94, 78, 78, 78, 125, 219, 200, 220, 125, 125, + 298, 84, 84, 159, 159, 159, 159, 159, 159, 159, + 159, 74, 79, 81, 111, 112, 125, 74, 113, 81, + 134, 108, 114, 82, 247, 115, 83, 83, 83, 83, + + 83, 83, 83, 83, 92, 126, 93, 93, 93, 93, + 93, 93, 93, 93, 94, 187, 248, 74, 95, 95, + 95, 95, 95, 254, 74, 155, 156, 157, 155, 155, + 155, 155, 155, 74, 299, 74, 262, 95, 95, 95, + 95, 95, 95, 73, 74, 259, 74, 73, 297, 73, + 399, 399, 73, 73, 74, 73, 73, 73, 101, 101, + 101, 101, 101, 101, 101, 101, 94, 74, 354, 73, + 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 74, 102, 95, + 95, 95, 95, 95, 95, 73, 73, 73, 73, 73, + + 73, 73, 73, 73, 73, 102, 102, 102, 102, 102, + 102, 102, 102, 553, 231, 231, 231, 102, 102, 102, + 102, 102, 83, 83, 83, 83, 83, 83, 83, 83, + 74, 74, 488, 134, 108, 294, 73, 73, 73, 73, + 73, 73, 107, 108, 73, 81, 73, 345, 73, 73, + 74, 87, 73, 87, 161, 87, 261, 87, 87, 235, + 161, 87, 553, 200, 73, 73, 73, 81, 136, 237, + 354, 136, 136, 87, 87, 87, 137, 82, 136, 94, + 83, 83, 83, 83, 83, 83, 83, 83, 89, 488, + 73, 136, 89, 81, 73, 73, 452, 258, 89, 124, + + 74, 73, 247, 124, 90, 73, 73, 511, 90, 124, + 89, 89, 73, 74, 90, 553, 161, 260, 116, 81, + 74, 124, 124, 73, 248, 237, 90, 90, 389, 133, + 344, 504, 553, 553, 553, 553, 553, 553, 553, 553, + 78, 387, 78, 148, 78, 332, 78, 78, 161, 336, + 78, 553, 553, 553, 553, 553, 553, 553, 553, 161, + 74, 161, 78, 78, 78, 300, 161, 333, 200, 74, + 152, 337, 152, 338, 152, 237, 152, 152, 340, 74, + 152, 433, 81, 79, 158, 158, 158, 158, 158, 158, + 158, 158, 152, 152, 152, 339, 158, 158, 158, 158, + + 158, 224, 225, 226, 224, 224, 224, 224, 224, 240, + 240, 240, 240, 240, 241, 158, 158, 158, 158, 158, + 158, 164, 164, 164, 164, 164, 164, 164, 164, 343, + 74, 431, 81, 164, 164, 164, 164, 164, 187, 452, + 188, 188, 188, 188, 188, 188, 282, 282, 282, 282, + 282, 283, 158, 158, 158, 158, 158, 158, 187, 74, + 188, 188, 188, 188, 188, 188, 188, 188, 346, 74, + 205, 205, 205, 205, 205, 205, 205, 205, 125, 432, + 402, 354, 125, 449, 449, 235, 161, 475, 125, 74, + 187, 356, 189, 189, 189, 189, 189, 189, 189, 189, + + 125, 125, 229, 229, 230, 231, 231, 231, 231, 231, + 197, 239, 239, 239, 239, 239, 239, 239, 239, 553, + 161, 74, 187, 553, 190, 190, 190, 190, 190, 191, + 188, 188, 553, 356, 238, 238, 238, 238, 238, 238, + 238, 238, 268, 268, 268, 268, 268, 268, 268, 268, + 197, 74, 473, 74, 73, 161, 192, 192, 192, 192, + 192, 192, 192, 192, 237, 466, 466, 384, 192, 192, + 192, 192, 192, 273, 274, 275, 273, 273, 273, 273, + 273, 325, 325, 325, 325, 325, 326, 192, 192, 192, + 192, 192, 192, 194, 195, 196, 196, 196, 196, 196, + + 196, 197, 485, 485, 81, 198, 198, 198, 198, 198, + 246, 246, 246, 246, 246, 246, 246, 246, 359, 359, + 359, 359, 359, 360, 198, 198, 198, 198, 198, 198, + 161, 201, 202, 203, 201, 201, 201, 201, 201, 204, + 235, 161, 74, 205, 205, 205, 205, 205, 235, 161, + 277, 277, 277, 277, 277, 277, 332, 336, 237, 504, + 505, 74, 205, 205, 205, 205, 205, 205, 206, 206, + 206, 206, 206, 206, 206, 206, 338, 390, 333, 337, + 206, 206, 206, 206, 206, 281, 281, 281, 281, 281, + 281, 281, 281, 502, 425, 161, 235, 161, 339, 192, + + 192, 192, 192, 192, 192, 187, 237, 188, 188, 188, + 188, 188, 188, 188, 188, 553, 426, 280, 280, 280, + 280, 280, 280, 280, 280, 301, 302, 303, 301, 301, + 301, 301, 301, 517, 517, 74, 74, 187, 161, 188, + 188, 188, 188, 188, 188, 188, 188, 279, 235, 161, + 471, 436, 524, 81, 74, 553, 161, 262, 279, 263, + 263, 263, 263, 263, 263, 279, 532, 532, 74, 235, + 161, 236, 236, 236, 236, 236, 236, 236, 236, 237, + 235, 161, 74, 238, 238, 238, 238, 238, 74, 313, + 279, 314, 314, 314, 314, 314, 314, 314, 314, 402, + + 356, 443, 238, 238, 238, 238, 238, 238, 161, 242, + 243, 244, 242, 242, 242, 242, 242, 245, 74, 475, + 473, 246, 246, 246, 246, 246, 313, 388, 315, 315, + 315, 315, 315, 315, 315, 315, 468, 235, 161, 412, + 246, 246, 246, 246, 246, 246, 262, 322, 263, 263, + 263, 263, 263, 263, 263, 263, 313, 427, 316, 316, + 316, 316, 316, 317, 314, 314, 288, 288, 288, 288, + 288, 288, 288, 288, 425, 356, 307, 74, 262, 428, + 264, 264, 264, 264, 264, 264, 264, 264, 235, 161, + 320, 320, 320, 320, 320, 320, 426, 354, 279, 324, + + 324, 324, 324, 324, 324, 324, 324, 356, 506, 74, + 262, 354, 265, 265, 265, 265, 265, 266, 263, 263, + 553, 402, 323, 323, 323, 323, 323, 323, 323, 323, + 312, 312, 312, 312, 312, 312, 312, 312, 74, 74, + 430, 74, 235, 161, 277, 277, 277, 277, 277, 277, + 277, 277, 237, 235, 161, 278, 278, 278, 278, 278, + 278, 278, 278, 279, 429, 74, 307, 280, 280, 280, + 280, 280, 358, 358, 358, 358, 358, 358, 358, 358, + 376, 376, 376, 376, 376, 377, 280, 280, 280, 280, + 280, 280, 161, 284, 285, 286, 284, 284, 284, 284, + + 284, 287, 161, 233, 386, 288, 288, 288, 288, 288, + 553, 279, 357, 357, 357, 357, 357, 357, 357, 357, + 385, 553, 161, 383, 288, 288, 288, 288, 288, 288, + 262, 322, 263, 263, 263, 263, 263, 263, 263, 263, + 366, 367, 368, 366, 366, 366, 366, 366, 313, 161, + 314, 314, 314, 314, 314, 314, 314, 314, 322, 382, + 313, 74, 262, 553, 263, 263, 263, 263, 263, 263, + 263, 263, 313, 402, 314, 314, 314, 314, 314, 314, + 314, 314, 313, 161, 314, 314, 314, 314, 314, 314, + 431, 81, 322, 74, 308, 309, 310, 308, 308, 308, + + 308, 308, 311, 469, 307, 233, 312, 312, 312, 312, + 312, 331, 331, 331, 331, 331, 331, 331, 331, 405, + 405, 405, 405, 405, 406, 312, 312, 312, 312, 312, + 312, 235, 161, 320, 320, 320, 320, 320, 320, 320, + 320, 279, 235, 161, 321, 321, 321, 321, 321, 321, + 321, 321, 322, 197, 342, 341, 323, 323, 323, 323, + 323, 235, 161, 371, 371, 371, 371, 371, 371, 427, + 335, 322, 334, 307, 233, 323, 323, 323, 323, 323, + 323, 161, 327, 328, 329, 327, 327, 327, 327, 327, + 330, 428, 197, 197, 331, 331, 331, 331, 331, 375, + + 375, 375, 375, 375, 375, 375, 375, 423, 423, 423, + 423, 423, 424, 331, 331, 331, 331, 331, 331, 347, + 348, 348, 348, 348, 348, 348, 348, 348, 553, 255, + 374, 374, 374, 374, 374, 374, 374, 374, 391, 392, + 393, 394, 391, 391, 391, 391, 524, 81, 535, 74, + 347, 349, 349, 349, 349, 349, 349, 349, 349, 534, + 347, 348, 348, 348, 348, 348, 348, 74, 396, 397, + 398, 396, 396, 396, 396, 396, 296, 295, 293, 74, + 74, 347, 350, 350, 350, 350, 350, 351, 348, 348, + 74, 365, 365, 365, 365, 365, 365, 365, 365, 404, + + 404, 404, 404, 404, 404, 404, 404, 292, 291, 290, + 289, 74, 354, 271, 355, 355, 355, 355, 355, 355, + 355, 355, 356, 161, 233, 197, 357, 357, 357, 357, + 357, 553, 373, 403, 403, 403, 403, 403, 403, 403, + 403, 267, 197, 100, 255, 357, 357, 357, 357, 357, + 357, 361, 362, 363, 361, 361, 361, 361, 361, 364, + 257, 255, 256, 365, 365, 365, 365, 365, 412, 354, + 413, 413, 413, 413, 413, 413, 413, 413, 255, 402, + 253, 252, 365, 365, 365, 365, 365, 365, 235, 161, + 371, 371, 371, 371, 371, 371, 371, 371, 322, 235, + + 161, 372, 372, 372, 372, 372, 372, 372, 372, 373, + 251, 250, 249, 374, 374, 374, 374, 374, 412, 354, + 414, 414, 414, 414, 414, 414, 414, 414, 94, 452, + 197, 233, 374, 374, 374, 374, 374, 374, 161, 378, + 379, 380, 378, 378, 378, 378, 378, 235, 161, 197, + 100, 381, 381, 381, 381, 381, 412, 322, 415, 415, + 415, 415, 415, 416, 413, 413, 81, 185, 221, 218, + 381, 381, 381, 381, 381, 381, 347, 348, 348, 348, + 348, 348, 348, 348, 348, 235, 161, 381, 381, 381, + 381, 381, 381, 381, 381, 373, 422, 422, 422, 422, + + 422, 422, 422, 422, 217, 216, 74, 347, 348, 348, + 348, 348, 348, 348, 348, 348, 553, 161, 235, 161, + 419, 419, 419, 419, 419, 419, 373, 553, 373, 421, + 421, 421, 421, 421, 421, 421, 421, 74, 354, 215, + 400, 400, 400, 400, 400, 400, 400, 400, 356, 354, + 553, 401, 401, 401, 401, 401, 401, 401, 401, 402, + 452, 214, 212, 403, 403, 403, 403, 403, 443, 161, + 444, 444, 444, 444, 444, 444, 444, 444, 373, 211, + 210, 209, 403, 403, 403, 403, 403, 403, 407, 408, + 409, 407, 407, 407, 407, 407, 410, 208, 207, 100, + + 411, 411, 411, 411, 411, 443, 354, 445, 445, 445, + 445, 445, 445, 445, 445, 92, 452, 153, 81, 411, + 411, 411, 411, 411, 411, 235, 161, 419, 419, 419, + 419, 419, 419, 419, 419, 373, 235, 161, 420, 420, + 420, 420, 420, 420, 420, 420, 81, 235, 161, 74, + 421, 421, 421, 421, 421, 434, 443, 373, 446, 446, + 446, 446, 446, 447, 444, 444, 480, 480, 480, 421, + 421, 421, 421, 421, 421, 434, 185, 434, 435, 411, + 411, 411, 411, 411, 411, 411, 411, 454, 454, 454, + 454, 454, 454, 454, 454, 74, 74, 436, 142, 437, + + 437, 437, 437, 437, 437, 437, 437, 455, 455, 455, + 455, 455, 456, 553, 354, 453, 453, 453, 453, 453, + 453, 453, 453, 143, 488, 137, 137, 129, 74, 436, + 183, 438, 438, 438, 438, 438, 438, 438, 438, 462, + 463, 464, 462, 462, 462, 462, 462, 412, 553, 413, + 413, 413, 413, 413, 413, 413, 413, 122, 488, 176, + 74, 436, 354, 439, 439, 439, 439, 439, 440, 441, + 441, 412, 488, 413, 413, 413, 413, 413, 413, 413, + 413, 412, 175, 413, 413, 413, 413, 413, 413, 434, + 174, 173, 74, 436, 172, 442, 442, 442, 437, 437, + + 437, 437, 437, 491, 491, 491, 491, 491, 492, 434, + 170, 434, 434, 169, 165, 100, 436, 73, 480, 480, + 480, 100, 154, 88, 74, 354, 153, 450, 450, 450, + 450, 450, 450, 450, 450, 402, 354, 81, 451, 451, + 451, 451, 451, 451, 451, 451, 452, 74, 148, 149, + 453, 453, 453, 453, 453, 476, 477, 478, 476, 476, + 476, 476, 476, 522, 522, 522, 522, 522, 523, 453, + 453, 453, 453, 453, 453, 457, 458, 459, 457, 457, + 457, 457, 457, 460, 74, 76, 75, 461, 461, 461, + 461, 461, 481, 482, 483, 481, 481, 481, 481, 481, + + 540, 540, 540, 540, 540, 540, 461, 461, 461, 461, + 461, 461, 235, 161, 467, 467, 467, 467, 467, 467, + 467, 467, 436, 74, 441, 441, 441, 441, 441, 441, + 441, 441, 443, 143, 444, 444, 444, 444, 444, 444, + 444, 444, 443, 137, 444, 444, 444, 444, 444, 444, + 444, 444, 129, 74, 436, 122, 441, 441, 441, 441, + 441, 441, 441, 441, 443, 121, 444, 444, 444, 444, + 444, 444, 461, 461, 461, 461, 461, 461, 461, 461, + 120, 119, 118, 117, 106, 74, 436, 105, 441, 441, + 441, 441, 441, 441, 479, 479, 490, 490, 490, 490, + + 490, 490, 490, 490, 553, 104, 489, 489, 489, 489, + 489, 489, 489, 489, 103, 100, 88, 74, 436, 76, + 479, 479, 479, 479, 479, 479, 479, 479, 161, 497, + 497, 497, 497, 497, 497, 497, 497, 161, 498, 498, + 498, 498, 498, 498, 498, 498, 75, 74, 553, 74, + 354, 553, 486, 486, 486, 486, 486, 486, 486, 486, + 452, 354, 553, 487, 487, 487, 487, 487, 487, 487, + 487, 488, 553, 553, 553, 489, 489, 489, 489, 489, + 161, 499, 499, 499, 499, 499, 500, 497, 497, 553, + 553, 553, 553, 553, 489, 489, 489, 489, 489, 489, + + 493, 494, 495, 493, 493, 493, 493, 493, 553, 553, + 553, 553, 496, 496, 496, 496, 496, 472, 553, 472, + 553, 472, 553, 472, 472, 553, 553, 472, 553, 553, + 553, 496, 496, 496, 496, 496, 496, 553, 553, 472, + 472, 472, 474, 553, 474, 553, 474, 553, 474, 474, + 553, 553, 474, 479, 479, 479, 479, 479, 479, 479, + 479, 553, 553, 553, 474, 474, 474, 506, 553, 507, + 507, 507, 507, 507, 507, 507, 507, 553, 553, 553, + 553, 511, 74, 512, 512, 512, 512, 512, 512, 512, + 512, 161, 497, 497, 497, 497, 497, 497, 74, 506, + + 553, 508, 508, 508, 508, 508, 508, 508, 508, 511, + 553, 513, 513, 513, 513, 513, 513, 513, 513, 511, + 553, 514, 514, 514, 514, 514, 515, 512, 512, 553, + 74, 506, 553, 509, 509, 509, 509, 509, 510, 507, + 507, 496, 496, 496, 496, 496, 496, 496, 496, 521, + 521, 521, 521, 521, 521, 521, 521, 553, 553, 553, + 553, 553, 74, 354, 553, 518, 518, 518, 518, 518, + 518, 518, 518, 488, 354, 553, 519, 519, 519, 519, + 519, 519, 519, 519, 553, 553, 553, 553, 520, 520, + 520, 520, 520, 553, 553, 520, 520, 520, 520, 520, + + 520, 520, 520, 553, 553, 553, 553, 520, 520, 520, + 520, 520, 520, 161, 497, 497, 497, 497, 497, 497, + 497, 497, 161, 497, 497, 497, 497, 497, 497, 497, + 497, 525, 526, 527, 525, 525, 525, 525, 525, 553, + 506, 553, 507, 507, 507, 507, 507, 507, 528, 529, + 530, 528, 528, 528, 528, 528, 553, 553, 553, 553, + 74, 506, 553, 507, 507, 507, 507, 507, 507, 507, + 507, 74, 511, 553, 512, 512, 512, 512, 512, 512, + 512, 512, 511, 553, 512, 512, 512, 512, 512, 512, + 512, 512, 74, 506, 553, 507, 507, 507, 507, 507, + + 507, 507, 507, 511, 553, 512, 512, 512, 512, 512, + 512, 354, 553, 533, 533, 533, 533, 533, 533, 533, + 533, 553, 553, 553, 74, 535, 553, 536, 536, 536, + 536, 536, 536, 536, 536, 540, 540, 540, 540, 540, + 540, 540, 540, 541, 541, 541, 541, 541, 541, 541, + 541, 553, 553, 553, 553, 553, 74, 535, 553, 537, + 537, 537, 537, 537, 537, 537, 537, 542, 542, 542, + 542, 542, 543, 540, 540, 547, 548, 549, 547, 547, + 547, 547, 547, 553, 553, 553, 553, 553, 74, 535, + 553, 538, 538, 538, 538, 538, 539, 536, 536, 553, + + 553, 553, 553, 535, 74, 536, 536, 536, 536, 536, + 536, 540, 540, 540, 540, 540, 540, 540, 540, 553, + 74, 535, 553, 536, 536, 536, 536, 536, 536, 536, + 536, 553, 553, 553, 74, 540, 540, 540, 540, 540, + 540, 540, 540, 550, 550, 550, 550, 550, 550, 550, + 550, 553, 74, 535, 553, 536, 536, 536, 536, 536, + 536, 536, 536, 547, 547, 547, 547, 547, 547, 547, + 547, 553, 74, 551, 551, 551, 551, 551, 552, 550, + 550, 553, 553, 553, 74, 550, 550, 550, 550, 550, + 550, 553, 74, 550, 550, 550, 550, 550, 550, 550, + + 550, 553, 74, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 74, 553, 553, 553, 553, 553, + 553, 553, 74, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 73, 553, 553, 553, 73, + 553, 73, 73, 73, 553, 73, 73, 73, 77, 77, + 553, 77, 77, 77, 77, 77, 77, 77, 77, 77, + + 77, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 84, 553, 553, 553, 84, 553, + 84, 84, 84, 84, 84, 84, 84, 87, 553, 553, + 553, 87, 553, 87, 87, 87, 553, 87, 87, 87, + 89, 553, 553, 89, 89, 553, 89, 89, 89, 553, + 89, 89, 89, 99, 99, 553, 553, 99, 124, 553, + 553, 124, 124, 553, 124, 124, 124, 553, 124, 124, + 124, 128, 553, 553, 128, 128, 128, 128, 128, 128, + 553, 553, 128, 128, 135, 135, 136, 553, 553, 136, + 553, 553, 136, 136, 136, 136, 136, 136, 136, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 142, 142, 553, 142, 553, 142, 142, 142, + 142, 142, 142, 142, 142, 78, 78, 553, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 151, 151, 553, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 152, 553, 553, 553, 152, 553, + 152, 152, 152, 553, 152, 152, 152, 90, 553, 553, + 90, 90, 553, 90, 90, 90, 553, 90, 90, 90, + 160, 160, 553, 553, 160, 162, 162, 162, 553, 553, + + 162, 125, 553, 553, 125, 125, 553, 125, 125, 125, + 553, 125, 125, 125, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 193, 193, 553, + 553, 193, 199, 199, 199, 553, 553, 199, 227, 227, + 553, 553, 227, 228, 228, 553, 553, 228, 232, 232, + 553, 553, 232, 234, 234, 234, 553, 553, 234, 267, + 267, 553, 553, 267, 269, 269, 553, 553, 269, 270, + 270, 553, 553, 270, 272, 272, 272, 553, 553, 272, + 276, 276, 276, 276, 553, 553, 276, 304, 304, 553, + 553, 304, 305, 305, 553, 553, 305, 306, 306, 553, + + 553, 306, 318, 318, 318, 553, 553, 318, 319, 319, + 319, 319, 553, 553, 319, 352, 352, 553, 553, 352, + 353, 353, 553, 553, 353, 369, 369, 369, 553, 553, + 369, 370, 370, 370, 370, 553, 553, 370, 395, 395, + 553, 553, 395, 399, 553, 399, 399, 553, 553, 399, + 417, 417, 417, 553, 553, 417, 418, 418, 418, 418, + 553, 553, 418, 448, 448, 553, 553, 448, 449, 553, + 449, 449, 553, 553, 449, 465, 465, 465, 553, 553, + 465, 466, 466, 466, 553, 553, 553, 466, 472, 553, + 553, 553, 472, 553, 472, 472, 472, 553, 472, 472, + + 472, 474, 553, 553, 553, 474, 553, 474, 474, 474, + 553, 474, 474, 474, 484, 484, 553, 553, 484, 485, + 553, 485, 485, 553, 553, 485, 501, 501, 553, 553, + 553, 501, 503, 503, 503, 503, 503, 503, 503, 503, + 503, 503, 503, 503, 503, 516, 516, 553, 553, 516, + 517, 553, 517, 517, 553, 553, 517, 531, 531, 553, + 553, 531, 532, 553, 532, 553, 553, 553, 532, 544, + 553, 553, 553, 544, 545, 545, 545, 545, 545, 545, + 545, 545, 545, 545, 545, 545, 545, 13, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553 } ; -static yyconst short int yy_chk[3416] = +static yyconst short int yy_chk[3551] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -924,376 +944,390 @@ static yyconst short int yy_chk[3416] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 4, 247, 2, 3, 4, 95, - 5, 5, 5, 114, 5, 247, 3, 4, 95, 39, - 5, 11, 11, 11, 11, 6, 6, 6, 114, 6, - 2, 2, 5, 5, 2, 6, 39, 62, 2, 50, - - 64, 2, 12, 12, 12, 12, 68, 6, 6, 69, - 24, 58, 58, 5, 24, 24, 50, 62, 66, 66, - 64, 3, 4, 169, 11, 169, 102, 102, 6, 7, - 7, 7, 24, 7, 26, 26, 26, 26, 26, 26, - 26, 26, 104, 71, 71, 12, 71, 104, 111, 68, - 69, 24, 27, 27, 27, 27, 27, 27, 38, 112, - 38, 38, 38, 38, 38, 38, 38, 38, 40, 102, - 530, 112, 7, 7, 7, 7, 7, 7, 7, 7, + 1, 1, 2, 3, 4, 116, 2, 3, 4, 550, + 5, 5, 5, 119, 5, 20, 3, 4, 59, 59, + 5, 11, 11, 11, 11, 6, 6, 6, 119, 6, + 2, 2, 5, 5, 2, 6, 20, 84, 2, 40, + + 51, 2, 12, 12, 12, 12, 63, 6, 6, 70, + 25, 67, 67, 5, 25, 25, 40, 51, 84, 116, + 109, 3, 4, 65, 11, 109, 63, 69, 6, 7, + 7, 7, 25, 7, 27, 27, 27, 27, 27, 27, + 27, 27, 121, 65, 432, 12, 72, 72, 121, 72, + 70, 25, 28, 28, 28, 28, 28, 28, 39, 117, + 39, 39, 39, 39, 39, 39, 39, 39, 41, 348, + 69, 117, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 116, 8, 516, 40, 40, 121, 116, + 8, 8, 8, 100, 8, 432, 41, 41, 127, 348, - 40, 166, 111, 121, 40, 48, 166, 40, 48, 48, - 48, 48, 48, 48, 48, 48, 78, 78, 78, 78, - 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, - 79, 79, 113, 8, 8, 8, 8, 8, 8, 8, + 41, 178, 100, 127, 41, 49, 178, 41, 49, 49, + 49, 49, 49, 49, 49, 49, 82, 82, 82, 82, + 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, + 83, 83, 118, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 115, 124, 124, 49, - 9, 9, 9, 49, 49, 56, 56, 56, 115, 56, - 113, 99, 137, 56, 9, 56, 99, 209, 99, 84, - 159, 49, 150, 84, 84, 127, 127, 56, 56, 139, - 139, 150, 209, 159, 9, 10, 10, 10, 10, 10, - - 49, 84, 165, 168, 10, 10, 10, 73, 56, 73, - 138, 73, 514, 73, 73, 137, 504, 73, 10, 168, - 84, 87, 87, 87, 87, 87, 87, 87, 87, 73, - 73, 73, 93, 93, 93, 93, 93, 93, 10, 18, - 91, 91, 91, 91, 91, 91, 91, 91, 165, 18, - 87, 138, 18, 18, 18, 18, 18, 18, 18, 18, - 25, 175, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 206, 503, 170, 25, 25, 25, 25, 25, 92, - 92, 92, 92, 92, 92, 92, 92, 170, 172, 179, - 246, 25, 175, 25, 25, 25, 25, 25, 25, 31, - - 200, 172, 194, 31, 501, 31, 200, 246, 31, 31, - 179, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 206, 194, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 183, 183, 183, 33, 33, 33, 33, 33, 186, 207, - 207, 221, 259, 500, 118, 134, 134, 186, 118, 118, - 221, 259, 33, 33, 33, 33, 33, 33, 37, 37, - - 37, 496, 37, 286, 37, 37, 118, 81, 37, 81, - 210, 81, 234, 81, 81, 488, 210, 81, 250, 286, - 37, 37, 37, 41, 105, 118, 208, 241, 134, 81, - 81, 81, 241, 41, 234, 486, 41, 41, 41, 41, - 41, 41, 41, 41, 83, 245, 83, 208, 83, 250, - 83, 83, 105, 105, 83, 86, 105, 86, 482, 86, - 105, 86, 86, 105, 208, 86, 83, 83, 83, 470, - 223, 223, 225, 225, 41, 57, 248, 86, 86, 86, - 223, 248, 225, 276, 279, 57, 347, 347, 57, 57, - 57, 57, 57, 57, 57, 57, 88, 88, 88, 88, - - 88, 88, 88, 88, 245, 276, 279, 330, 88, 88, - 88, 88, 88, 174, 174, 174, 174, 174, 174, 174, - 174, 190, 190, 190, 190, 190, 190, 88, 88, 88, - 88, 88, 88, 96, 96, 96, 96, 96, 96, 96, - 96, 280, 174, 284, 263, 96, 96, 96, 96, 96, - 120, 469, 120, 263, 120, 330, 120, 120, 374, 374, - 120, 264, 264, 280, 96, 96, 96, 96, 96, 96, - 459, 264, 120, 120, 120, 130, 285, 142, 130, 130, - 281, 142, 287, 265, 265, 130, 285, 142, 305, 281, - 284, 287, 171, 265, 457, 319, 171, 305, 130, 142, - - 142, 143, 171, 143, 143, 143, 143, 143, 143, 143, - 143, 375, 456, 375, 171, 171, 178, 319, 178, 178, - 178, 178, 178, 178, 187, 187, 187, 187, 187, 187, - 187, 187, 143, 144, 306, 144, 144, 144, 144, 144, - 144, 144, 144, 306, 323, 393, 393, 178, 182, 182, - 182, 182, 182, 182, 182, 182, 182, 231, 231, 231, - 231, 231, 231, 455, 144, 145, 323, 145, 145, 145, - 145, 145, 145, 145, 145, 189, 189, 189, 189, 189, - 189, 189, 189, 192, 342, 192, 192, 192, 192, 192, - 192, 192, 192, 327, 342, 332, 145, 146, 335, 146, - - 146, 146, 146, 146, 146, 146, 146, 325, 454, 327, - 332, 146, 146, 146, 146, 146, 216, 216, 216, 216, - 216, 216, 216, 216, 216, 369, 407, 407, 335, 325, - 146, 146, 146, 146, 146, 146, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 408, 408, 369, 149, 149, - 149, 149, 149, 222, 222, 222, 222, 222, 222, 222, - 222, 273, 273, 273, 273, 273, 273, 149, 149, 149, - 149, 149, 149, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 411, 411, 452, 151, 151, 151, 151, - 151, 224, 224, 224, 224, 224, 224, 224, 224, 297, - - 297, 297, 297, 297, 297, 151, 151, 151, 151, 151, - 151, 152, 152, 152, 152, 152, 152, 152, 152, 370, - 333, 435, 419, 152, 152, 152, 152, 152, 228, 228, - 228, 228, 228, 228, 228, 228, 333, 419, 228, 267, - 267, 370, 152, 152, 152, 152, 152, 152, 176, 267, - 176, 176, 176, 176, 176, 176, 176, 176, 230, 230, - 230, 230, 230, 230, 230, 230, 233, 331, 233, 233, - 233, 233, 233, 233, 233, 233, 331, 418, 418, 176, - 177, 344, 177, 177, 177, 177, 177, 177, 177, 177, - 418, 344, 434, 387, 249, 249, 249, 249, 249, 249, - - 249, 249, 253, 387, 253, 253, 253, 253, 253, 253, - 430, 177, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 249, 442, 442, 188, 188, 188, 188, - 188, 423, 260, 253, 260, 260, 260, 260, 260, 260, - 260, 260, 453, 453, 421, 188, 188, 188, 188, 188, - 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 356, 423, 420, 191, 191, 191, 191, 191, 261, - 356, 261, 261, 261, 261, 261, 261, 261, 261, 416, - 307, 307, 400, 191, 191, 191, 191, 191, 191, 211, - 307, 211, 211, 211, 211, 211, 211, 211, 211, 262, - - 412, 262, 262, 262, 262, 262, 262, 262, 262, 266, - 266, 266, 266, 266, 266, 266, 266, 414, 477, 477, - 211, 212, 412, 212, 212, 212, 212, 212, 212, 212, - 212, 270, 270, 270, 270, 270, 270, 270, 270, 414, - 388, 270, 272, 272, 272, 272, 272, 272, 272, 272, - 388, 491, 212, 213, 390, 213, 213, 213, 213, 213, - 213, 213, 213, 275, 390, 275, 275, 275, 275, 275, - 275, 275, 275, 294, 294, 294, 294, 294, 294, 294, - 294, 386, 491, 382, 213, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 229, 229, 229, 229, - - 229, 229, 229, 229, 229, 229, 229, 507, 507, 377, - 229, 229, 229, 229, 229, 296, 296, 296, 296, 296, - 296, 296, 296, 316, 316, 316, 316, 316, 316, 229, - 229, 229, 229, 229, 229, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 357, 373, 372, 232, 232, - 232, 232, 232, 299, 357, 299, 299, 299, 299, 299, - 299, 299, 299, 371, 308, 308, 340, 232, 232, 232, - 232, 232, 232, 251, 308, 251, 251, 251, 251, 251, - 251, 251, 251, 300, 300, 300, 300, 300, 300, 300, - 300, 302, 404, 302, 302, 302, 302, 302, 302, 302, - - 302, 404, 518, 339, 251, 252, 436, 252, 252, 252, - 252, 252, 252, 252, 252, 303, 436, 303, 303, 303, - 303, 303, 303, 303, 303, 304, 405, 304, 304, 304, - 304, 304, 304, 518, 329, 405, 252, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 328, 322, 321, 258, - 258, 258, 258, 258, 309, 309, 309, 309, 309, 309, - 309, 309, 350, 350, 350, 350, 350, 350, 258, 258, - 258, 258, 258, 258, 268, 268, 268, 268, 268, 268, - 268, 268, 268, 268, 268, 271, 271, 271, 271, 271, - 271, 271, 271, 271, 271, 271, 310, 310, 301, 271, - - 271, 271, 271, 271, 293, 437, 310, 313, 313, 313, - 313, 313, 313, 313, 313, 437, 292, 313, 271, 271, - 271, 271, 271, 271, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 291, 283, 282, 274, 274, 274, - 274, 274, 315, 315, 315, 315, 315, 315, 315, 315, - 367, 367, 367, 367, 367, 367, 274, 274, 274, 274, - 274, 274, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 318, 278, 318, 318, 318, 318, 318, 318, 318, - 318, 334, 334, 334, 334, 334, 334, 334, 334, 277, - 257, 256, 288, 289, 289, 289, 289, 289, 289, 289, - - 289, 289, 255, 338, 338, 338, 338, 338, 338, 338, - 334, 341, 341, 341, 341, 341, 341, 341, 341, 254, - 244, 243, 242, 289, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 338, 343, 343, 343, 343, 343, 343, - 343, 343, 349, 349, 349, 349, 349, 349, 349, 349, - 240, 239, 238, 237, 290, 295, 439, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 439, 236, 220, 295, - 295, 295, 295, 295, 352, 451, 352, 352, 352, 352, - 352, 352, 352, 352, 451, 219, 218, 217, 295, 295, - 295, 295, 295, 295, 298, 298, 298, 298, 298, 298, - - 298, 298, 298, 215, 214, 205, 298, 298, 298, 298, - 298, 353, 471, 353, 353, 353, 353, 353, 353, 353, - 353, 204, 471, 203, 202, 298, 298, 298, 298, 298, - 298, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 201, 199, 198, 314, 314, 314, 314, - 314, 354, 472, 354, 354, 354, 354, 354, 354, 354, - 354, 197, 472, 196, 195, 314, 314, 314, 314, 314, - 314, 317, 317, 317, 317, 317, 317, 317, 317, 317, - 358, 358, 193, 185, 317, 317, 317, 317, 317, 355, - - 358, 355, 355, 355, 355, 355, 355, 355, 355, 184, - 181, 180, 173, 317, 317, 317, 317, 317, 317, 336, - 336, 336, 336, 336, 336, 336, 336, 336, 359, 359, - 360, 360, 360, 360, 360, 360, 360, 360, 359, 366, - 366, 366, 366, 366, 366, 366, 366, 167, 164, 336, - 337, 337, 337, 337, 337, 337, 337, 337, 337, 361, - 361, 364, 364, 364, 364, 364, 364, 364, 364, 361, - 368, 364, 368, 368, 368, 368, 368, 368, 368, 368, - 337, 345, 163, 345, 345, 345, 345, 345, 345, 345, - 345, 345, 348, 474, 348, 348, 348, 348, 348, 348, - - 348, 348, 348, 474, 162, 161, 348, 348, 348, 348, - 348, 383, 502, 383, 383, 383, 383, 383, 383, 383, - 383, 160, 502, 158, 157, 348, 348, 348, 348, 348, - 348, 351, 351, 351, 351, 351, 351, 351, 351, 351, - 156, 155, 154, 351, 351, 351, 351, 351, 384, 153, - 384, 384, 384, 384, 384, 384, 384, 384, 148, 147, - 141, 140, 351, 351, 351, 351, 351, 351, 362, 362, - 362, 362, 362, 362, 362, 362, 362, 362, 362, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 136, - 406, 406, 135, 365, 365, 365, 365, 365, 376, 385, - - 406, 385, 385, 385, 385, 385, 385, 385, 385, 465, - 465, 465, 365, 365, 365, 365, 365, 365, 376, 133, - 376, 376, 389, 389, 389, 389, 389, 389, 389, 389, - 395, 395, 395, 395, 395, 395, 395, 395, 465, 376, - 378, 129, 378, 378, 378, 378, 378, 378, 378, 378, - 396, 396, 396, 396, 396, 396, 398, 123, 398, 398, - 398, 398, 398, 398, 398, 398, 119, 117, 110, 109, - 108, 378, 379, 107, 379, 379, 379, 379, 379, 379, - 379, 379, 399, 399, 399, 399, 399, 399, 399, 399, - 401, 106, 401, 401, 401, 401, 401, 401, 401, 401, - - 101, 100, 98, 379, 380, 94, 380, 380, 380, 380, - 380, 380, 380, 380, 402, 90, 402, 402, 402, 402, - 402, 402, 402, 402, 403, 89, 403, 403, 403, 403, - 403, 403, 417, 85, 82, 380, 381, 80, 381, 381, - 381, 381, 381, 381, 381, 381, 445, 445, 445, 445, - 445, 445, 417, 76, 417, 417, 75, 74, 72, 428, - 67, 428, 428, 428, 60, 53, 47, 381, 391, 46, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 394, - 45, 394, 394, 394, 394, 394, 394, 394, 394, 394, - 428, 44, 43, 394, 394, 394, 394, 394, 422, 422, - - 422, 422, 422, 422, 422, 422, 480, 480, 480, 480, - 480, 480, 394, 394, 394, 394, 394, 394, 397, 397, - 397, 397, 397, 397, 397, 397, 397, 422, 42, 36, - 397, 397, 397, 397, 397, 429, 429, 429, 429, 429, - 429, 429, 429, 525, 525, 525, 525, 525, 525, 397, - 397, 397, 397, 397, 397, 409, 409, 409, 409, 409, - 409, 409, 409, 409, 409, 424, 35, 424, 424, 424, - 424, 424, 424, 424, 424, 431, 34, 431, 431, 431, - 431, 431, 431, 431, 431, 432, 32, 432, 432, 432, - 432, 432, 432, 432, 432, 28, 424, 425, 22, 425, - - 425, 425, 425, 425, 425, 425, 425, 433, 19, 433, - 433, 433, 433, 433, 433, 438, 438, 438, 438, 438, - 438, 438, 438, 17, 15, 14, 13, 0, 425, 426, - 0, 426, 426, 426, 426, 426, 426, 426, 426, 444, - 444, 444, 444, 444, 444, 444, 444, 447, 0, 447, - 447, 447, 447, 447, 447, 447, 447, 0, 0, 0, - 426, 427, 0, 427, 427, 427, 427, 427, 427, 427, - 427, 448, 448, 448, 448, 448, 448, 448, 448, 448, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 0, - 0, 0, 427, 440, 0, 440, 440, 440, 440, 440, - - 440, 440, 440, 440, 443, 0, 443, 443, 443, 443, - 443, 443, 443, 443, 443, 0, 0, 0, 443, 443, - 443, 443, 443, 450, 450, 450, 450, 450, 450, 450, - 450, 450, 0, 0, 0, 0, 0, 443, 443, 443, - 443, 443, 443, 446, 446, 446, 446, 446, 446, 446, - 446, 0, 0, 0, 0, 446, 446, 446, 446, 446, - 458, 0, 458, 0, 458, 0, 458, 458, 0, 0, - 458, 0, 0, 0, 446, 446, 446, 446, 446, 446, - 0, 0, 458, 458, 458, 460, 0, 460, 0, 460, - 0, 460, 460, 0, 0, 460, 464, 464, 464, 464, - - 464, 464, 464, 464, 0, 0, 0, 460, 460, 460, - 461, 0, 461, 461, 461, 461, 461, 461, 461, 461, - 0, 0, 0, 0, 466, 464, 466, 466, 466, 466, - 466, 466, 466, 466, 485, 485, 485, 485, 485, 485, - 485, 461, 462, 0, 462, 462, 462, 462, 462, 462, - 462, 462, 467, 0, 467, 467, 467, 467, 467, 467, - 467, 467, 468, 0, 468, 468, 468, 468, 468, 468, - 468, 468, 0, 462, 463, 0, 463, 463, 463, 463, - 463, 463, 463, 463, 473, 473, 473, 473, 473, 473, - 473, 473, 479, 479, 479, 479, 479, 479, 479, 479, - - 0, 0, 0, 0, 0, 463, 475, 0, 475, 475, - 475, 475, 475, 475, 475, 475, 475, 478, 0, 478, - 478, 478, 478, 478, 478, 478, 478, 0, 0, 0, - 0, 478, 478, 478, 478, 478, 481, 0, 481, 481, - 481, 481, 481, 481, 481, 481, 0, 0, 0, 0, - 478, 478, 478, 478, 478, 478, 483, 483, 483, 483, - 483, 483, 483, 483, 483, 484, 484, 484, 484, 484, - 484, 484, 484, 484, 490, 490, 490, 490, 490, 490, - 490, 490, 0, 494, 0, 494, 494, 494, 494, 494, - 494, 495, 495, 495, 495, 495, 495, 495, 495, 0, - - 0, 0, 0, 490, 492, 0, 492, 492, 492, 492, - 492, 492, 492, 492, 494, 497, 0, 497, 497, 497, - 497, 497, 497, 497, 497, 498, 0, 498, 498, 498, - 498, 498, 498, 498, 498, 492, 493, 0, 493, 493, - 493, 493, 493, 493, 493, 493, 499, 0, 499, 499, - 499, 499, 499, 499, 505, 0, 505, 505, 505, 505, - 505, 505, 505, 505, 0, 0, 0, 493, 508, 0, - 508, 508, 508, 508, 508, 508, 508, 508, 511, 511, - 511, 511, 511, 511, 511, 511, 512, 512, 512, 512, - 512, 512, 512, 512, 0, 0, 0, 0, 0, 508, - - 509, 0, 509, 509, 509, 509, 509, 509, 509, 509, - 513, 513, 513, 513, 513, 513, 513, 513, 517, 517, - 517, 517, 517, 517, 517, 517, 0, 0, 0, 0, - 0, 509, 510, 0, 510, 510, 510, 510, 510, 510, - 510, 510, 0, 0, 0, 0, 521, 517, 521, 521, - 521, 521, 521, 521, 523, 523, 523, 523, 523, 523, - 523, 523, 0, 510, 519, 0, 519, 519, 519, 519, - 519, 519, 519, 519, 0, 0, 0, 521, 524, 524, - 524, 524, 524, 524, 524, 524, 527, 527, 527, 527, - 527, 527, 527, 527, 0, 519, 520, 0, 520, 520, - - 520, 520, 520, 520, 520, 520, 528, 528, 528, 528, - 528, 528, 528, 528, 0, 527, 529, 529, 529, 529, - 529, 529, 529, 529, 0, 0, 0, 520, 532, 532, - 532, 532, 532, 532, 0, 528, 531, 531, 531, 531, - 531, 531, 531, 531, 0, 529, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 532, 0, 0, - 0, 0, 0, 0, 0, 531, 534, 534, 534, 534, - 534, 534, 534, 534, 534, 534, 534, 534, 534, 535, - 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, - 535, 535, 536, 536, 536, 536, 536, 536, 536, 536, - - 536, 536, 536, 536, 536, 537, 537, 537, 537, 537, - 537, 537, 537, 537, 537, 537, 537, 537, 538, 0, - 0, 0, 538, 0, 538, 538, 538, 0, 538, 538, - 538, 539, 539, 539, 539, 539, 539, 539, 539, 539, - 539, 539, 539, 539, 540, 0, 0, 0, 540, 0, - 540, 540, 540, 0, 540, 540, 540, 541, 0, 0, - 0, 541, 0, 541, 541, 541, 0, 541, 541, 541, - 542, 0, 0, 542, 542, 0, 542, 542, 542, 0, - 542, 542, 542, 543, 543, 0, 0, 543, 544, 0, - 0, 544, 544, 0, 544, 544, 544, 0, 544, 544, - - 544, 545, 0, 0, 545, 545, 545, 545, 545, 545, - 0, 0, 545, 545, 546, 546, 547, 0, 0, 547, - 0, 0, 547, 547, 547, 547, 547, 547, 547, 548, - 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, - 548, 548, 549, 549, 0, 549, 0, 549, 549, 549, - 549, 549, 549, 549, 549, 550, 550, 550, 550, 550, - 550, 550, 550, 550, 550, 550, 550, 550, 551, 0, - 0, 551, 551, 0, 551, 551, 551, 0, 551, 551, - 551, 552, 552, 0, 0, 552, 553, 553, 553, 0, - 0, 553, 554, 0, 0, 554, 554, 0, 554, 554, - - 554, 0, 554, 554, 554, 555, 555, 0, 0, 555, - 556, 556, 556, 0, 0, 556, 557, 557, 0, 0, - 557, 558, 558, 0, 0, 558, 559, 559, 0, 0, - 559, 560, 560, 560, 0, 0, 560, 561, 561, 0, - 0, 561, 562, 562, 0, 0, 562, 563, 563, 0, - 0, 563, 564, 564, 564, 0, 0, 564, 565, 565, - 565, 565, 0, 0, 565, 566, 566, 0, 0, 566, - 567, 567, 0, 0, 567, 568, 568, 0, 0, 568, - 569, 569, 569, 0, 0, 569, 570, 570, 570, 570, - 0, 0, 570, 571, 571, 0, 0, 571, 572, 572, - - 0, 0, 572, 573, 573, 573, 0, 0, 573, 574, - 574, 574, 574, 0, 0, 574, 575, 575, 0, 0, - 575, 576, 0, 576, 576, 0, 0, 576, 577, 577, - 577, 0, 0, 577, 578, 578, 578, 578, 0, 0, - 578, 579, 579, 0, 0, 579, 580, 0, 580, 580, - 0, 0, 580, 581, 581, 581, 0, 0, 581, 582, - 582, 582, 0, 0, 0, 582, 583, 0, 0, 0, - 583, 0, 583, 583, 583, 0, 583, 583, 583, 584, - 0, 0, 0, 584, 0, 584, 584, 584, 0, 584, - 584, 584, 585, 585, 0, 0, 585, 586, 0, 586, - - 586, 0, 0, 586, 587, 587, 0, 0, 0, 587, - 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, - 588, 588, 588, 589, 589, 0, 0, 589, 590, 0, - 590, 590, 0, 0, 590, 591, 591, 0, 0, 591, - 592, 0, 592, 0, 0, 0, 592, 593, 0, 0, - 0, 593, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - - 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 533, 533, 533, 533, 533 + 8, 9, 9, 9, 9, 9, 120, 130, 130, 50, + 9, 9, 9, 50, 50, 57, 57, 57, 120, 57, + 118, 104, 144, 57, 9, 57, 104, 222, 104, 89, + 171, 50, 162, 89, 89, 134, 134, 57, 57, 146, + 146, 162, 222, 171, 9, 10, 10, 10, 10, 10, + + 50, 89, 182, 145, 10, 10, 10, 74, 57, 74, + 181, 74, 181, 74, 74, 144, 182, 74, 10, 177, + 89, 96, 96, 96, 96, 96, 96, 96, 96, 74, + 74, 74, 98, 98, 98, 98, 98, 98, 10, 18, + 184, 18, 18, 18, 145, 18, 18, 545, 86, 18, + 86, 180, 86, 184, 86, 86, 110, 199, 86, 534, + 192, 18, 18, 18, 124, 177, 199, 180, 124, 124, + 259, 86, 86, 97, 97, 97, 97, 97, 97, 97, + 97, 192, 18, 19, 110, 110, 124, 259, 110, 258, + 107, 107, 110, 19, 207, 110, 19, 19, 19, 19, + + 19, 19, 19, 19, 26, 124, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 188, 207, 213, 26, 26, + 26, 26, 26, 213, 260, 92, 92, 92, 92, 92, + 92, 92, 92, 107, 260, 26, 263, 26, 26, 26, + 26, 26, 26, 32, 220, 220, 188, 32, 258, 32, + 360, 360, 32, 32, 92, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 263, 533, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + + 32, 32, 32, 32, 32, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 196, 196, 196, 34, 34, 34, + 34, 34, 123, 123, 123, 123, 123, 123, 123, 123, + 254, 299, 531, 141, 141, 254, 34, 34, 34, 34, + 34, 34, 38, 38, 38, 219, 38, 299, 38, 38, + 223, 88, 38, 88, 234, 88, 223, 88, 88, 236, + 236, 88, 520, 234, 38, 38, 38, 42, 137, 236, + 519, 137, 137, 88, 88, 88, 141, 42, 137, 221, + 42, 42, 42, 42, 42, 42, 42, 42, 91, 517, + 91, 137, 91, 343, 91, 91, 516, 219, 91, 126, + + 221, 126, 247, 126, 154, 126, 126, 512, 154, 126, + 91, 91, 91, 345, 154, 238, 238, 221, 42, 58, + 298, 126, 126, 126, 247, 238, 154, 154, 345, 58, + 298, 503, 58, 58, 58, 58, 58, 58, 58, 58, + 77, 343, 77, 77, 77, 289, 77, 77, 501, 292, + 77, 133, 133, 133, 133, 133, 133, 133, 133, 272, + 261, 497, 77, 77, 77, 261, 276, 289, 272, 294, + 153, 292, 153, 293, 153, 276, 153, 153, 294, 388, + 153, 388, 297, 77, 93, 93, 93, 93, 93, 93, + 93, 93, 153, 153, 153, 293, 93, 93, 93, 93, + + 93, 187, 187, 187, 187, 187, 187, 187, 187, 203, + 203, 203, 203, 203, 203, 93, 93, 93, 93, 93, + 93, 101, 101, 101, 101, 101, 101, 101, 101, 297, + 187, 387, 387, 101, 101, 101, 101, 101, 191, 485, + 191, 191, 191, 191, 191, 191, 244, 244, 244, 244, + 244, 244, 101, 101, 101, 101, 101, 101, 155, 300, + 155, 155, 155, 155, 155, 155, 155, 155, 300, 191, + 200, 200, 200, 200, 200, 200, 200, 200, 183, 387, + 484, 355, 183, 406, 406, 420, 420, 474, 183, 155, + 156, 355, 156, 156, 156, 156, 156, 156, 156, 156, + + 183, 183, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 202, 202, 202, 202, 202, 202, 202, 202, 421, + 421, 156, 157, 357, 157, 157, 157, 157, 157, 157, + 157, 157, 205, 357, 205, 205, 205, 205, 205, 205, + 205, 205, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 340, 472, 157, 158, 318, 158, 158, 158, 158, + 158, 158, 158, 158, 318, 424, 424, 340, 158, 158, + 158, 158, 158, 235, 235, 235, 235, 235, 235, 235, + 235, 286, 286, 286, 286, 286, 286, 158, 158, 158, + 158, 158, 158, 161, 161, 161, 161, 161, 161, 161, + + 161, 161, 456, 456, 470, 161, 161, 161, 161, 161, + 237, 237, 237, 237, 237, 237, 237, 237, 310, 310, + 310, 310, 310, 310, 161, 161, 161, 161, 161, 161, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 467, 467, 471, 163, 163, 163, 163, 163, 241, 241, + 241, 241, 241, 241, 241, 241, 332, 336, 241, 469, + 470, 346, 163, 163, 163, 163, 163, 163, 164, 164, + 164, 164, 164, 164, 164, 164, 338, 346, 332, 336, + 164, 164, 164, 164, 164, 243, 243, 243, 243, 243, + 243, 243, 243, 468, 382, 466, 277, 277, 338, 164, + + 164, 164, 164, 164, 164, 189, 277, 189, 189, 189, + 189, 189, 189, 189, 189, 246, 382, 246, 246, 246, + 246, 246, 246, 246, 246, 262, 262, 262, 262, 262, + 262, 262, 262, 492, 492, 433, 189, 190, 319, 190, + 190, 190, 190, 190, 190, 190, 190, 319, 278, 278, + 433, 437, 505, 505, 262, 280, 280, 266, 278, 266, + 266, 266, 266, 266, 266, 280, 523, 523, 190, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 320, 320, 437, 201, 201, 201, 201, 201, 266, 273, + 320, 273, 273, 273, 273, 273, 273, 273, 273, 449, + + 448, 444, 201, 201, 201, 201, 201, 201, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 344, 435, + 434, 204, 204, 204, 204, 204, 274, 344, 274, 274, + 274, 274, 274, 274, 274, 274, 429, 321, 321, 413, + 204, 204, 204, 204, 204, 204, 224, 321, 224, 224, + 224, 224, 224, 224, 224, 224, 275, 383, 275, 275, + 275, 275, 275, 275, 275, 275, 279, 279, 279, 279, + 279, 279, 279, 279, 425, 399, 395, 224, 225, 383, + 225, 225, 225, 225, 225, 225, 225, 225, 283, 283, + 283, 283, 283, 283, 283, 283, 425, 400, 283, 285, + + 285, 285, 285, 285, 285, 285, 285, 400, 507, 225, + 226, 401, 226, 226, 226, 226, 226, 226, 226, 226, + 288, 401, 288, 288, 288, 288, 288, 288, 288, 288, + 307, 307, 307, 307, 307, 307, 307, 307, 390, 507, + 386, 226, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 385, 384, 353, 242, 242, 242, + 242, 242, 309, 309, 309, 309, 309, 309, 309, 309, + 329, 329, 329, 329, 329, 329, 242, 242, 242, 242, + 242, 242, 245, 245, 245, 245, 245, 245, 245, 245, + + 245, 245, 369, 352, 342, 245, 245, 245, 245, 245, + 312, 369, 312, 312, 312, 312, 312, 312, 312, 312, + 341, 323, 323, 335, 245, 245, 245, 245, 245, 245, + 264, 323, 264, 264, 264, 264, 264, 264, 264, 264, + 313, 313, 313, 313, 313, 313, 313, 313, 315, 370, + 315, 315, 315, 315, 315, 315, 315, 315, 370, 334, + 314, 264, 265, 403, 265, 265, 265, 265, 265, 265, + 265, 265, 316, 403, 316, 316, 316, 316, 316, 316, + 316, 316, 317, 417, 317, 317, 317, 317, 317, 317, + 431, 431, 417, 265, 271, 271, 271, 271, 271, 271, + + 271, 271, 271, 431, 306, 305, 271, 271, 271, 271, + 271, 322, 322, 322, 322, 322, 322, 322, 322, 363, + 363, 363, 363, 363, 363, 271, 271, 271, 271, 271, + 271, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 304, 296, 295, 284, 284, 284, 284, + 284, 326, 326, 326, 326, 326, 326, 326, 326, 427, + 291, 326, 290, 270, 269, 284, 284, 284, 284, 284, + 284, 287, 287, 287, 287, 287, 287, 287, 287, 287, + 287, 427, 268, 267, 287, 287, 287, 287, 287, 328, + + 328, 328, 328, 328, 328, 328, 328, 380, 380, 380, + 380, 380, 380, 287, 287, 287, 287, 287, 287, 301, + 301, 301, 301, 301, 301, 301, 301, 301, 331, 257, + 331, 331, 331, 331, 331, 331, 331, 331, 347, 347, + 347, 347, 347, 347, 347, 347, 524, 524, 536, 301, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 524, + 351, 351, 351, 351, 351, 351, 351, 347, 354, 354, + 354, 354, 354, 354, 354, 354, 256, 255, 253, 536, + 302, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 351, 356, 356, 356, 356, 356, 356, 356, 356, 362, + + 362, 362, 362, 362, 362, 362, 362, 252, 251, 250, + 249, 303, 308, 233, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 418, 232, 231, 308, 308, 308, 308, + 308, 365, 418, 365, 365, 365, 365, 365, 365, 365, + 365, 230, 228, 227, 218, 308, 308, 308, 308, 308, + 308, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 217, 216, 215, 311, 311, 311, 311, 311, 366, 450, + 366, 366, 366, 366, 366, 366, 366, 366, 214, 450, + 212, 211, 311, 311, 311, 311, 311, 311, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 327, + + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 210, 209, 208, 327, 327, 327, 327, 327, 367, 451, + 367, 367, 367, 367, 367, 367, 367, 367, 206, 451, + 198, 197, 327, 327, 327, 327, 327, 327, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 371, 371, 194, + 193, 330, 330, 330, 330, 330, 368, 371, 368, 368, + 368, 368, 368, 368, 368, 368, 186, 185, 179, 176, + 330, 330, 330, 330, 330, 330, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 372, 372, 373, 373, 373, + 373, 373, 373, 373, 373, 372, 379, 379, 379, 379, + + 379, 379, 379, 379, 175, 174, 349, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 374, 374, 377, 377, + 377, 377, 377, 377, 377, 377, 374, 381, 377, 381, + 381, 381, 381, 381, 381, 381, 381, 350, 358, 173, + 358, 358, 358, 358, 358, 358, 358, 358, 358, 361, + 453, 361, 361, 361, 361, 361, 361, 361, 361, 361, + 453, 172, 170, 361, 361, 361, 361, 361, 396, 465, + 396, 396, 396, 396, 396, 396, 396, 396, 465, 169, + 168, 167, 361, 361, 361, 361, 361, 361, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 166, 165, 160, + + 364, 364, 364, 364, 364, 397, 486, 397, 397, 397, + 397, 397, 397, 397, 397, 159, 486, 152, 151, 364, + 364, 364, 364, 364, 364, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 378, 378, 378, 378, + 378, 378, 378, 378, 378, 378, 150, 419, 419, 148, + 378, 378, 378, 378, 378, 389, 398, 419, 398, 398, + 398, 398, 398, 398, 398, 398, 480, 480, 480, 378, + 378, 378, 378, 378, 378, 389, 147, 389, 389, 402, + 402, 402, 402, 402, 402, 402, 402, 408, 408, 408, + 408, 408, 408, 408, 408, 480, 389, 391, 143, 391, + + 391, 391, 391, 391, 391, 391, 391, 409, 409, 409, + 409, 409, 409, 411, 487, 411, 411, 411, 411, 411, + 411, 411, 411, 142, 487, 140, 136, 129, 391, 392, + 125, 392, 392, 392, 392, 392, 392, 392, 392, 412, + 412, 412, 412, 412, 412, 412, 412, 414, 489, 414, + 414, 414, 414, 414, 414, 414, 414, 122, 489, 115, + 392, 393, 518, 393, 393, 393, 393, 393, 393, 393, + 393, 415, 518, 415, 415, 415, 415, 415, 415, 415, + 415, 416, 114, 416, 416, 416, 416, 416, 416, 430, + 113, 112, 393, 394, 111, 394, 394, 394, 394, 394, + + 394, 394, 394, 459, 459, 459, 459, 459, 459, 430, + 106, 430, 430, 105, 103, 99, 442, 95, 442, 442, + 442, 94, 90, 87, 394, 404, 85, 404, 404, 404, + 404, 404, 404, 404, 404, 404, 407, 80, 407, 407, + 407, 407, 407, 407, 407, 407, 407, 442, 79, 78, + 407, 407, 407, 407, 407, 436, 436, 436, 436, 436, + 436, 436, 436, 495, 495, 495, 495, 495, 495, 407, + 407, 407, 407, 407, 407, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 436, 76, 75, 410, 410, 410, + 410, 410, 443, 443, 443, 443, 443, 443, 443, 443, + + 543, 543, 543, 543, 543, 543, 410, 410, 410, 410, + 410, 410, 422, 422, 422, 422, 422, 422, 422, 422, + 422, 422, 438, 73, 438, 438, 438, 438, 438, 438, + 438, 438, 445, 68, 445, 445, 445, 445, 445, 445, + 445, 445, 446, 61, 446, 446, 446, 446, 446, 446, + 446, 446, 54, 438, 439, 48, 439, 439, 439, 439, + 439, 439, 439, 439, 447, 47, 447, 447, 447, 447, + 447, 447, 452, 452, 452, 452, 452, 452, 452, 452, + 46, 45, 44, 43, 37, 439, 440, 36, 440, 440, + 440, 440, 440, 440, 440, 440, 458, 458, 458, 458, + + 458, 458, 458, 458, 461, 35, 461, 461, 461, 461, + 461, 461, 461, 461, 33, 29, 23, 440, 441, 17, + 441, 441, 441, 441, 441, 441, 441, 441, 462, 462, + 462, 462, 462, 462, 462, 462, 462, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 15, 14, 13, 441, + 454, 0, 454, 454, 454, 454, 454, 454, 454, 454, + 454, 457, 0, 457, 457, 457, 457, 457, 457, 457, + 457, 457, 0, 0, 0, 457, 457, 457, 457, 457, + 464, 464, 464, 464, 464, 464, 464, 464, 464, 0, + 0, 0, 0, 0, 457, 457, 457, 457, 457, 457, + + 460, 460, 460, 460, 460, 460, 460, 460, 0, 0, + 0, 0, 460, 460, 460, 460, 460, 473, 0, 473, + 0, 473, 0, 473, 473, 0, 0, 473, 0, 0, + 0, 460, 460, 460, 460, 460, 460, 0, 0, 473, + 473, 473, 475, 0, 475, 0, 475, 0, 475, 475, + 0, 0, 475, 479, 479, 479, 479, 479, 479, 479, + 479, 0, 0, 0, 475, 475, 475, 476, 0, 476, + 476, 476, 476, 476, 476, 476, 476, 0, 0, 0, + 0, 481, 479, 481, 481, 481, 481, 481, 481, 481, + 481, 500, 500, 500, 500, 500, 500, 500, 476, 477, + + 0, 477, 477, 477, 477, 477, 477, 477, 477, 482, + 0, 482, 482, 482, 482, 482, 482, 482, 482, 483, + 0, 483, 483, 483, 483, 483, 483, 483, 483, 0, + 477, 478, 0, 478, 478, 478, 478, 478, 478, 478, + 478, 488, 488, 488, 488, 488, 488, 488, 488, 494, + 494, 494, 494, 494, 494, 494, 494, 0, 0, 0, + 0, 0, 478, 490, 0, 490, 490, 490, 490, 490, + 490, 490, 490, 490, 493, 0, 493, 493, 493, 493, + 493, 493, 493, 493, 0, 0, 0, 0, 493, 493, + 493, 493, 493, 496, 0, 496, 496, 496, 496, 496, + + 496, 496, 496, 0, 0, 0, 0, 493, 493, 493, + 493, 493, 493, 498, 498, 498, 498, 498, 498, 498, + 498, 498, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 506, 506, 506, 506, 506, 506, 506, 506, 0, + 510, 0, 510, 510, 510, 510, 510, 510, 511, 511, + 511, 511, 511, 511, 511, 511, 0, 0, 0, 0, + 506, 508, 0, 508, 508, 508, 508, 508, 508, 508, + 508, 510, 513, 0, 513, 513, 513, 513, 513, 513, + 513, 513, 514, 0, 514, 514, 514, 514, 514, 514, + 514, 514, 508, 509, 0, 509, 509, 509, 509, 509, + + 509, 509, 509, 515, 0, 515, 515, 515, 515, 515, + 515, 521, 0, 521, 521, 521, 521, 521, 521, 521, + 521, 0, 0, 0, 509, 525, 0, 525, 525, 525, + 525, 525, 525, 525, 525, 528, 528, 528, 528, 528, + 528, 528, 528, 529, 529, 529, 529, 529, 529, 529, + 529, 0, 0, 0, 0, 0, 525, 526, 0, 526, + 526, 526, 526, 526, 526, 526, 526, 530, 530, 530, + 530, 530, 530, 530, 530, 535, 535, 535, 535, 535, + 535, 535, 535, 0, 0, 0, 0, 0, 526, 527, + 0, 527, 527, 527, 527, 527, 527, 527, 527, 0, + + 0, 0, 0, 539, 535, 539, 539, 539, 539, 539, + 539, 541, 541, 541, 541, 541, 541, 541, 541, 0, + 527, 537, 0, 537, 537, 537, 537, 537, 537, 537, + 537, 0, 0, 0, 539, 542, 542, 542, 542, 542, + 542, 542, 542, 547, 547, 547, 547, 547, 547, 547, + 547, 0, 537, 538, 0, 538, 538, 538, 538, 538, + 538, 538, 538, 548, 548, 548, 548, 548, 548, 548, + 548, 0, 547, 549, 549, 549, 549, 549, 549, 549, + 549, 0, 0, 0, 538, 552, 552, 552, 552, 552, + 552, 0, 548, 551, 551, 551, 551, 551, 551, 551, + + 551, 0, 549, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 552, 0, 0, 0, 0, 0, + 0, 0, 551, 554, 554, 554, 554, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 555, 555, 555, 555, + 555, 555, 555, 555, 555, 555, 555, 555, 555, 556, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 557, 557, 557, 557, 557, 557, 557, 557, + 557, 557, 557, 557, 557, 558, 0, 0, 0, 558, + 0, 558, 558, 558, 0, 558, 558, 558, 559, 559, + 0, 559, 559, 559, 559, 559, 559, 559, 559, 559, + + 559, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 561, 0, 0, 0, 561, 0, + 561, 561, 561, 561, 561, 561, 561, 562, 0, 0, + 0, 562, 0, 562, 562, 562, 0, 562, 562, 562, + 563, 0, 0, 563, 563, 0, 563, 563, 563, 0, + 563, 563, 563, 564, 564, 0, 0, 564, 565, 0, + 0, 565, 565, 0, 565, 565, 565, 0, 565, 565, + 565, 566, 0, 0, 566, 566, 566, 566, 566, 566, + 0, 0, 566, 566, 567, 567, 568, 0, 0, 568, + 0, 0, 568, 568, 568, 568, 568, 568, 568, 569, + + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 570, 570, 0, 570, 0, 570, 570, 570, + 570, 570, 570, 570, 570, 571, 571, 0, 571, 571, + 571, 571, 571, 571, 571, 571, 571, 571, 572, 572, + 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, + 572, 573, 573, 0, 573, 573, 573, 573, 573, 573, + 573, 573, 573, 573, 574, 0, 0, 0, 574, 0, + 574, 574, 574, 0, 574, 574, 574, 575, 0, 0, + 575, 575, 0, 575, 575, 575, 0, 575, 575, 575, + 576, 576, 0, 0, 576, 577, 577, 577, 0, 0, + + 577, 578, 0, 0, 578, 578, 0, 578, 578, 578, + 0, 578, 578, 578, 579, 579, 579, 579, 579, 579, + 579, 579, 579, 579, 579, 579, 579, 580, 580, 0, + 0, 580, 581, 581, 581, 0, 0, 581, 582, 582, + 0, 0, 582, 583, 583, 0, 0, 583, 584, 584, + 0, 0, 584, 585, 585, 585, 0, 0, 585, 586, + 586, 0, 0, 586, 587, 587, 0, 0, 587, 588, + 588, 0, 0, 588, 589, 589, 589, 0, 0, 589, + 590, 590, 590, 590, 0, 0, 590, 591, 591, 0, + 0, 591, 592, 592, 0, 0, 592, 593, 593, 0, + + 0, 593, 594, 594, 594, 0, 0, 594, 595, 595, + 595, 595, 0, 0, 595, 596, 596, 0, 0, 596, + 597, 597, 0, 0, 597, 598, 598, 598, 0, 0, + 598, 599, 599, 599, 599, 0, 0, 599, 600, 600, + 0, 0, 600, 601, 0, 601, 601, 0, 0, 601, + 602, 602, 602, 0, 0, 602, 603, 603, 603, 603, + 0, 0, 603, 604, 604, 0, 0, 604, 605, 0, + 605, 605, 0, 0, 605, 606, 606, 606, 0, 0, + 606, 607, 607, 607, 0, 0, 0, 607, 608, 0, + 0, 0, 608, 0, 608, 608, 608, 0, 608, 608, + + 608, 609, 0, 0, 0, 609, 0, 609, 609, 609, + 0, 609, 609, 609, 610, 610, 0, 0, 610, 611, + 0, 611, 611, 0, 0, 611, 612, 612, 0, 0, + 0, 612, 613, 613, 613, 613, 613, 613, 613, 613, + 613, 613, 613, 613, 613, 614, 614, 0, 0, 614, + 615, 0, 615, 615, 0, 0, 615, 616, 616, 0, + 0, 616, 617, 0, 617, 0, 0, 0, 617, 618, + 0, 0, 0, 618, 619, 619, 619, 619, 619, 619, + 619, 619, 619, 619, 619, 619, 619, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553 } ; static yy_state_type yy_last_accepting_state; @@ -1311,7 +1345,7 @@ char *yytext; #define INITIAL 0 #line 2 "toke.l" /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -1338,6 +1372,7 @@ char *yytext; #include #include +#include #include #ifdef STDC_HEADERS # include @@ -1360,13 +1395,29 @@ char *yytext; #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif #include #include "sudo.h" #include "parse.h" #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: toke.c,v 1.27 2008/11/24 00:42:20 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: toke.c,v 1.36 2009/05/27 00:47:17 millert Exp $"; #endif /* lint */ extern YYSTYPE yylval; @@ -1380,15 +1431,16 @@ static int append __P((char *, int)); static int _fill __P((char *, int, int)); static int fill_cmnd __P((char *, int)); static int fill_args __P((char *, int, int)); -static int switch_buffer __P((char *)); +static int _push_include __P((char *, int)); +static int pop_include __P((void)); static int ipv6_valid __P((const char *s)); static char *parse_include __P((char *)); extern void yyerror __P((const char *)); #define fill(a, b) _fill(a, b, 0) -#define push_include(_p) (switch_buffer((_p))) -#define pop_include() (switch_buffer(NULL)) +#define push_include(_p) (_push_include((_p), FALSE)) +#define push_includedir(_p) (_push_include((_p), TRUE)) /* realloc() to size + COMMANDARGINC to make room for command args */ #define COMMANDARGINC 64 @@ -1409,7 +1461,7 @@ extern void yyerror __P((const char *)); #define INSTR 5 -#line 1413 "lex.yy.c" +#line 1465 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -1563,9 +1615,9 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 113 "toke.l" +#line 131 "toke.l" -#line 1569 "lex.yy.c" +#line 1621 "lex.yy.c" if ( yy_init ) { @@ -1617,13 +1669,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 534 ) + if ( yy_current_state >= 554 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 3353 ); + while ( yy_base[yy_current_state] != 3488 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1651,12 +1703,12 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 114 "toke.l" +#line 132 "toke.l" BEGIN STARTDEFS; YY_BREAK case 2: YY_RULE_SETUP -#line 116 "toke.l" +#line 134 "toke.l" { BEGIN INDEFS; LEXTRACE("DEFVAR "); @@ -1668,7 +1720,7 @@ YY_RULE_SETUP case 3: YY_RULE_SETUP -#line 125 "toke.l" +#line 143 "toke.l" { BEGIN STARTDEFS; LEXTRACE(", "); @@ -1677,7 +1729,7 @@ YY_RULE_SETUP YY_BREAK case 4: YY_RULE_SETUP -#line 131 "toke.l" +#line 149 "toke.l" { LEXTRACE("= "); return('='); @@ -1685,7 +1737,7 @@ YY_RULE_SETUP YY_BREAK case 5: YY_RULE_SETUP -#line 136 "toke.l" +#line 154 "toke.l" { LEXTRACE("+= "); return('+'); @@ -1693,7 +1745,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 141 "toke.l" +#line 159 "toke.l" { LEXTRACE("-= "); return('-'); @@ -1701,7 +1753,7 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 146 "toke.l" +#line 164 "toke.l" { LEXTRACE("BEGINSTR "); yylval.string = NULL; @@ -1710,7 +1762,7 @@ YY_RULE_SETUP YY_BREAK case 8: YY_RULE_SETUP -#line 152 "toke.l" +#line 170 "toke.l" { LEXTRACE("WORD(2) "); if (!fill(yytext, yyleng)) @@ -1722,7 +1774,7 @@ YY_RULE_SETUP case 9: YY_RULE_SETUP -#line 161 "toke.l" +#line 179 "toke.l" { /* Line continuation char followed by newline. */ ++sudolineno; @@ -1731,7 +1783,7 @@ YY_RULE_SETUP YY_BREAK case 10: YY_RULE_SETUP -#line 167 "toke.l" +#line 185 "toke.l" { LEXTRACE("ENDSTR "); BEGIN INDEFS; @@ -1740,7 +1792,7 @@ YY_RULE_SETUP YY_BREAK case 11: YY_RULE_SETUP -#line 173 "toke.l" +#line 191 "toke.l" { LEXTRACE("BACKSLASH "); if (!append(yytext, yyleng)) @@ -1749,7 +1801,7 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 179 "toke.l" +#line 197 "toke.l" { LEXTRACE("STRBODY "); if (!append(yytext, yyleng)) @@ -1760,7 +1812,7 @@ YY_RULE_SETUP case 13: YY_RULE_SETUP -#line 187 "toke.l" +#line 205 "toke.l" { /* quoted fnmatch glob char, pass verbatim */ LEXTRACE("QUOTEDCHAR "); @@ -1771,7 +1823,7 @@ YY_RULE_SETUP YY_BREAK case 14: YY_RULE_SETUP -#line 195 "toke.l" +#line 213 "toke.l" { /* quoted sudoers special char, strip backslash */ LEXTRACE("QUOTEDCHAR "); @@ -1782,7 +1834,7 @@ YY_RULE_SETUP YY_BREAK case 15: YY_RULE_SETUP -#line 203 "toke.l" +#line 221 "toke.l" { BEGIN INITIAL; yyless(0); @@ -1791,7 +1843,7 @@ YY_RULE_SETUP YY_BREAK case 16: YY_RULE_SETUP -#line 209 "toke.l" +#line 227 "toke.l" { LEXTRACE("ARG "); if (!fill_args(yytext, yyleng, sawspace)) @@ -1802,7 +1854,7 @@ YY_RULE_SETUP case 17: YY_RULE_SETUP -#line 217 "toke.l" +#line 235 "toke.l" { char *path; @@ -1818,7 +1870,23 @@ YY_RULE_SETUP YY_BREAK case 18: YY_RULE_SETUP -#line 230 "toke.l" +#line 248 "toke.l" +{ + char *path; + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDEDIR\n"); + + /* Push current buffer and switch to include file */ + if (!push_includedir(path)) + yyterminate(); + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 261 "toke.l" { int n; for (n = 0; isblank((unsigned char)yytext[n]); n++) @@ -1848,9 +1916,9 @@ YY_RULE_SETUP } } YY_BREAK -case 19: +case 20: YY_RULE_SETUP -#line 259 "toke.l" +#line 290 "toke.l" { int n; for (n = 0; isblank((unsigned char)yytext[n]); n++) @@ -1871,59 +1939,59 @@ YY_RULE_SETUP } } YY_BREAK -case 20: +case 21: YY_RULE_SETUP -#line 279 "toke.l" +#line 310 "toke.l" { /* cmnd does not require passwd for this user */ LEXTRACE("NOPASSWD "); return(NOPASSWD); } YY_BREAK -case 21: +case 22: YY_RULE_SETUP -#line 285 "toke.l" +#line 316 "toke.l" { /* cmnd requires passwd for this user */ LEXTRACE("PASSWD "); return(PASSWD); } YY_BREAK -case 22: +case 23: YY_RULE_SETUP -#line 291 "toke.l" +#line 322 "toke.l" { LEXTRACE("NOEXEC "); return(NOEXEC); } YY_BREAK -case 23: +case 24: YY_RULE_SETUP -#line 296 "toke.l" +#line 327 "toke.l" { LEXTRACE("EXEC "); return(EXEC); } YY_BREAK -case 24: +case 25: YY_RULE_SETUP -#line 301 "toke.l" +#line 332 "toke.l" { LEXTRACE("SETENV "); return(SETENV); } YY_BREAK -case 25: +case 26: YY_RULE_SETUP -#line 306 "toke.l" +#line 337 "toke.l" { LEXTRACE("NOSETENV "); return(NOSETENV); } YY_BREAK -case 26: +case 27: YY_RULE_SETUP -#line 311 "toke.l" +#line 342 "toke.l" { /* netgroup */ if (!fill(yytext, yyleng)) @@ -1932,9 +2000,9 @@ YY_RULE_SETUP return(NETGROUP); } YY_BREAK -case 27: +case 28: YY_RULE_SETUP -#line 319 "toke.l" +#line 350 "toke.l" { /* UN*X group */ if (!fill(yytext, yyleng)) @@ -1943,9 +2011,9 @@ YY_RULE_SETUP return(USERGROUP); } YY_BREAK -case 28: +case 29: YY_RULE_SETUP -#line 327 "toke.l" +#line 358 "toke.l" { if (!fill(yytext, yyleng)) yyterminate(); @@ -1953,9 +2021,9 @@ YY_RULE_SETUP return(NTWKADDR); } YY_BREAK -case 29: +case 30: YY_RULE_SETUP -#line 334 "toke.l" +#line 365 "toke.l" { if (!fill(yytext, yyleng)) yyterminate(); @@ -1963,9 +2031,9 @@ YY_RULE_SETUP return(NTWKADDR); } YY_BREAK -case 30: +case 31: YY_RULE_SETUP -#line 341 "toke.l" +#line 372 "toke.l" { if (!ipv6_valid(yytext)) { LEXTRACE("ERROR "); @@ -1977,9 +2045,9 @@ YY_RULE_SETUP return(NTWKADDR); } YY_BREAK -case 31: +case 32: YY_RULE_SETUP -#line 352 "toke.l" +#line 383 "toke.l" { if (!ipv6_valid(yytext)) { LEXTRACE("ERROR "); @@ -1991,9 +2059,9 @@ YY_RULE_SETUP return(NTWKADDR); } YY_BREAK -case 32: +case 33: YY_RULE_SETUP -#line 363 "toke.l" +#line 394 "toke.l" { if (strcmp(yytext, "ALL") == 0) { LEXTRACE("ALL "); @@ -2016,9 +2084,9 @@ YY_RULE_SETUP return(ALIAS); } YY_BREAK -case 33: +case 34: YY_RULE_SETUP -#line 385 "toke.l" +#line 416 "toke.l" { /* no command args allowed for Defaults!/path */ if (!fill_cmnd(yytext, yyleng)) @@ -2027,9 +2095,9 @@ YY_RULE_SETUP return(COMMAND); } YY_BREAK -case 34: +case 35: YY_RULE_SETUP -#line 393 "toke.l" +#line 424 "toke.l" { BEGIN GOTCMND; LEXTRACE("COMMAND "); @@ -2037,9 +2105,9 @@ YY_RULE_SETUP yyterminate(); } /* sudo -e */ YY_BREAK -case 35: +case 36: YY_RULE_SETUP -#line 400 "toke.l" +#line 431 "toke.l" { /* directories can't have args... */ if (yytext[yyleng - 1] == '/') { @@ -2055,68 +2123,88 @@ YY_RULE_SETUP } } /* a pathname */ YY_BREAK -case 36: +case 37: +YY_RULE_SETUP +#line 446 "toke.l" +{ + /* a quoted user/group name */ + if (!fill(yytext + 1, yyleng - 2)) + yyterminate(); + switch (yytext[1]) { + case '%': + LEXTRACE("USERGROUP "); + return(USERGROUP); + case '+': + LEXTRACE("NETGROUP "); + return(NETGROUP); + default: + LEXTRACE("WORD(4) "); + return(WORD); + } + } + YY_BREAK +case 38: YY_RULE_SETUP -#line 415 "toke.l" +#line 463 "toke.l" { /* a word */ if (!fill(yytext, yyleng)) yyterminate(); - LEXTRACE("WORD(4) "); + LEXTRACE("WORD(5) "); return(WORD); } YY_BREAK -case 37: +case 39: YY_RULE_SETUP -#line 423 "toke.l" +#line 471 "toke.l" { LEXTRACE("( "); return ('('); } YY_BREAK -case 38: +case 40: YY_RULE_SETUP -#line 428 "toke.l" +#line 476 "toke.l" { LEXTRACE(") "); return(')'); } YY_BREAK -case 39: +case 41: YY_RULE_SETUP -#line 433 "toke.l" +#line 481 "toke.l" { LEXTRACE(", "); return(','); } /* return ',' */ YY_BREAK -case 40: +case 42: YY_RULE_SETUP -#line 438 "toke.l" +#line 486 "toke.l" { LEXTRACE("= "); return('='); } /* return '=' */ YY_BREAK -case 41: +case 43: YY_RULE_SETUP -#line 443 "toke.l" +#line 491 "toke.l" { LEXTRACE(": "); return(':'); } /* return ':' */ YY_BREAK -case 42: +case 44: YY_RULE_SETUP -#line 448 "toke.l" +#line 496 "toke.l" { if (yyleng % 2 == 1) return('!'); /* return '!' */ } YY_BREAK -case 43: +case 45: YY_RULE_SETUP -#line 453 "toke.l" +#line 501 "toke.l" { BEGIN INITIAL; ++sudolineno; @@ -2124,35 +2212,35 @@ YY_RULE_SETUP return(COMMENT); } /* return newline */ YY_BREAK -case 44: +case 46: YY_RULE_SETUP -#line 460 "toke.l" +#line 508 "toke.l" { /* throw away space/tabs */ sawspace = TRUE; /* but remember for fill_args */ } YY_BREAK -case 45: +case 47: YY_RULE_SETUP -#line 464 "toke.l" +#line 512 "toke.l" { sawspace = TRUE; /* remember for fill_args */ ++sudolineno; LEXTRACE("\n\t"); } /* throw away EOL after \ */ YY_BREAK -case 46: +case 48: YY_RULE_SETUP -#line 470 "toke.l" +#line 518 "toke.l" { BEGIN INITIAL; ++sudolineno; LEXTRACE("\n"); return(COMMENT); - } /* return comments */ + } /* comment, not uid/gid */ YY_BREAK -case 47: +case 49: YY_RULE_SETUP -#line 477 "toke.l" +#line 525 "toke.l" { LEXTRACE("ERROR "); return(ERROR); @@ -2164,7 +2252,7 @@ case YY_STATE_EOF(GOTCMND): case YY_STATE_EOF(STARTDEFS): case YY_STATE_EOF(INDEFS): case YY_STATE_EOF(INSTR): -#line 482 "toke.l" +#line 530 "toke.l" { if (YY_START != INITIAL) { BEGIN INITIAL; @@ -2175,12 +2263,12 @@ case YY_STATE_EOF(INSTR): yyterminate(); } YY_BREAK -case 48: +case 50: YY_RULE_SETUP -#line 492 "toke.l" +#line 540 "toke.l" ECHO; YY_BREAK -#line 2184 "lex.yy.c" +#line 2272 "lex.yy.c" case YY_END_OF_BUFFER: { @@ -2471,7 +2559,7 @@ static yy_state_type yy_get_previous_state() while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 534 ) + if ( yy_current_state >= 554 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -2506,11 +2594,11 @@ yy_state_type yy_current_state; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 534 ) + if ( yy_current_state >= 554 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 533); + yy_is_jam = (yy_current_state == 553); return yy_is_jam ? 0 : yy_current_state; } @@ -3069,14 +3157,59 @@ int main() return 0; } #endif -#line 492 "toke.l" +#line 540 "toke.l" + +static unsigned char +hexchar(s) + const char *s; +{ + int i; + int result = 0; + + s += 2; /* skip \\x */ + for (i = 0; i < 2; i++) { + switch (*s) { + case 'A': + case 'a': + result += 10; + break; + case 'B': + case 'b': + result += 11; + break; + case 'C': + case 'c': + result += 12; + break; + case 'D': + case 'd': + result += 13; + break; + case 'E': + case 'e': + result += 14; + break; + case 'F': + case 'f': + result += 15; + break; + default: + result += *s - '0'; + break; + } + if (i == 0) { + result *= 16; + s++; + } + } + return((unsigned char)result); +} static int _fill(src, len, olen) char *src; int len, olen; { - int i, j; char *dst; dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); @@ -3088,13 +3221,24 @@ _fill(src, len, olen) /* Copy the string and collapse any escaped characters. */ dst += olen; - for (i = 0, j = 0; i < len; i++, j++) { - if (src[i] == '\\' && i != len - 1) - dst[j] = src[++i]; - else - dst[j] = src[i]; + while (len--) { + if (*src == '\\' && len) { + if (src[1] == 'x' && len >= 3 && + isxdigit((unsigned char) src[2]) && + isxdigit((unsigned char) src[3])) { + *dst++ = hexchar(src); + src += 4; + len -= 3; + } else { + src++; + len--; + *dst++ = *src++; + } + } else { + *dst++ = *src++; + } } - dst[j] = '\0'; + *dst = '\0'; return(TRUE); } @@ -3186,63 +3330,228 @@ fill_args(s, len, addspace) return(TRUE); } -struct sudoers_state { +struct path_list { + char *path; + struct path_list *next; +}; + +struct include_stack { YY_BUFFER_STATE bs; char *path; + struct path_list *more; /* more files in case of includedir */ int lineno; + int keepopen; }; +static int +pl_compare(v1, v2) + const void *v1; + const void *v2; +{ + const struct path_list * const *p1 = v1; + const struct path_list * const *p2 = v2; + + return(strcmp((*p1)->path, (*p2)->path)); +} + +static char * +switch_dir(stack, dirpath) + struct include_stack *stack; + char *dirpath; +{ + DIR *dir; + int i, count = 0; + char *path = NULL; + struct dirent *dent; + struct stat sb; + struct path_list *pl, *first = NULL; + struct path_list **sorted = NULL; + + if (!(dir = opendir(dirpath))) { + yyerror(dirpath); + return(FALSE); + } + while ((dent = readdir(dir))) { + /* Ignore files that end in '~' or have a '.' in them. */ + if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' + || strchr(dent->d_name, '.') != NULL) { + continue; + } + if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) { + closedir(dir); + goto bad; + } + if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) { + efree(path); + continue; + } + pl = malloc(sizeof(*pl)); + if (pl == NULL) + goto bad; + pl->path = path; + pl->next = first; + first = pl; + count++; + } + closedir(dir); + + if (count == 0) + goto done; + + /* Sort the list as an array. */ + sorted = malloc(sizeof(*sorted) * count); + if (sorted == NULL) + goto bad; + pl = first; + for (i = 0; i < count; i++) { + sorted[i] = pl; + pl = pl->next; + } + qsort(sorted, count, sizeof(*sorted), pl_compare); + + /* Apply sorting to the list. */ + first = sorted[0]; + sorted[count - 1]->next = NULL; + for (i = 1; i < count; i++) + sorted[i - 1]->next = sorted[i]; + efree(sorted); + + /* Pull out the first element for parsing, leave the rest for later. */ + if (count) { + path = first->path; + pl = first->next; + efree(first); + stack->more = pl; + } else { + path = NULL; + } +done: + efree(dirpath); + return(path); +bad: + while (first != NULL) { + pl = first; + first = pl->next; + free(pl->path); + free(pl); + } + efree(sorted); + efree(dirpath); + efree(path); + return(NULL); +} + #define MAX_SUDOERS_DEPTH 128 #define SUDOERS_STACK_INCREMENT 16 +static size_t istacksize, idepth; +static struct include_stack *istack; +static int keepopen; + +void +init_lexer() +{ + struct path_list *pl; + + while (idepth) { + idepth--; + while ((pl = istack[idepth].more) != NULL) { + istack[idepth].more = pl->next; + efree(pl->path); + efree(pl); + } + efree(istack[idepth].path); + if (!istack[idepth].keepopen) + fclose(istack[idepth].bs->yy_input_file); + yy_delete_buffer(istack[idepth].bs); + } + efree(istack); + istack = NULL; + istacksize = idepth = 0; + keepopen = FALSE; +} + static int -switch_buffer(path) +_push_include(path, isdir) char *path; + int isdir; { - static size_t stacksize, depth; - static struct sudoers_state *state; - static int keepopen; FILE *fp; - if (path != NULL) { - /* push current state */ - if (depth >= stacksize) { - if (depth > MAX_SUDOERS_DEPTH) { - yyerror("too many levels of includes"); - return(FALSE); - } - stacksize += SUDOERS_STACK_INCREMENT; - state = (struct sudoers_state *) realloc(state, - sizeof(state) * stacksize); - if (state == NULL) { - yyerror("unable to allocate memory"); - return(FALSE); - } + /* push current state onto stack */ + if (idepth >= istacksize) { + if (idepth > MAX_SUDOERS_DEPTH) { + yyerror("too many levels of includes"); + return(FALSE); + } + istacksize += SUDOERS_STACK_INCREMENT; + istack = (struct include_stack *) realloc(istack, + sizeof(istack) * istacksize); + if (istack == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } + } + if (isdir) { + if (!(path = switch_dir(&istack[idepth], path))) { + yyerror(path); + return(FALSE); + } + if ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { + yyerror(path); + return(FALSE); /* XXX - just to go next one? */ } - if ((fp = open_sudoers(path, &keepopen)) == NULL) { + } else { + if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { yyerror(path); return(FALSE); } - state[depth].bs = YY_CURRENT_BUFFER; - state[depth].path = sudoers; - state[depth].lineno = sudolineno; - depth++; + istack[idepth].more = NULL; + } + /* Push the old (current) file and open the new one. */ + istack[idepth].path = sudoers; /* push old path */ + istack[idepth].bs = YY_CURRENT_BUFFER; + istack[idepth].lineno = sudolineno; + istack[idepth].keepopen = keepopen; + idepth++; + sudolineno = 1; + sudoers = path; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + + return(TRUE); +} + +static int +pop_include() +{ + struct path_list *pl; + FILE *fp; + + if (idepth == 0) + return(FALSE); + + if (!keepopen) + fclose(YY_CURRENT_BUFFER->yy_input_file); + yy_delete_buffer(YY_CURRENT_BUFFER); + keepopen = FALSE; + if ((pl = istack[idepth - 1].more) != NULL) { + /* Move to next file in the dir. */ + istack[idepth - 1].more = pl->next; + if ((fp = open_sudoers(pl->path, FALSE, &keepopen)) == NULL) { + yyerror(pl->path); + return(FALSE); /* XXX - just to go next one? */ + } + efree(sudoers); + sudoers = pl->path; sudolineno = 1; - sudoers = path; yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + efree(pl); } else { - /* pop */ - if (depth == 0) - return(FALSE); - depth--; - if (!keepopen) - fclose(YY_CURRENT_BUFFER->yy_input_file); - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(state[depth].bs); + idepth--; + yy_switch_to_buffer(istack[idepth].bs); efree(sudoers); - sudoers = state[depth].path; - sudolineno = state[depth].lineno; - keepopen = FALSE; + sudoers = istack[idepth].path; + sudolineno = istack[idepth].lineno; } return(TRUE); } @@ -3252,22 +3561,45 @@ parse_include(base) char *base; { char *cp, *ep, *path; - int len; + int len = 0, subst = 0; + size_t shost_len = 0; /* Pull out path from #include line. */ cp = base + sizeof("#include"); + if (*cp == 'i') + cp += 3; /* includedir */ while (isblank((unsigned char) *cp)) cp++; ep = cp; - while (*ep != '\0' && !isspace((unsigned char) *ep)) + while (*ep != '\0' && !isspace((unsigned char) *ep)) { + if (ep[0] == '%' && ep[1] == 'h') { + shost_len = strlen(user_shost); + len += shost_len - 2; + subst = 1; + } ep++; + } /* Make a copy of path and return it. */ - len = (int)(ep - cp); + len += (int)(ep - cp); if ((path = malloc(len + 1)) == NULL) yyerror("unable to allocate memory"); - memcpy(path, cp, len); - path[len] = '\0'; + if (subst) { + /* substitute for %h */ + char *pp = path; + while (cp < ep) { + if (cp[0] == '%' && cp[1] == 'h') { + memcpy(pp, user_shost, shost_len); + pp += shost_len; + cp += 2; + } + *pp++ = *cp++; + } + *pp = '\0'; + } else { + memcpy(path, cp, len); + path[len] = '\0'; + } /* Push any excess characters (e.g. comment, newline) back to the lexer */ if (*ep != '\0') diff --git a/toke.l b/toke.l index a38da3a..9b93563 100644 --- a/toke.l +++ b/toke.l @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -27,6 +27,7 @@ #include #include +#include #include #ifdef STDC_HEADERS # include @@ -49,13 +50,29 @@ #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif #include #include "sudo.h" #include "parse.h" #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: toke.l,v 1.27 2008/11/24 00:41:36 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: toke.l,v 1.37 2009/05/27 00:46:51 millert Exp $"; #endif /* lint */ extern YYSTYPE yylval; @@ -69,15 +86,16 @@ static int append __P((char *, int)); static int _fill __P((char *, int, int)); static int fill_cmnd __P((char *, int)); static int fill_args __P((char *, int, int)); -static int switch_buffer __P((char *)); +static int _push_include __P((char *, int)); +static int pop_include __P((void)); static int ipv6_valid __P((const char *s)); static char *parse_include __P((char *)); extern void yyerror __P((const char *)); #define fill(a, b) _fill(a, b, 0) -#define push_include(_p) (switch_buffer((_p))) -#define pop_include() (switch_buffer(NULL)) +#define push_include(_p) (_push_include((_p), FALSE)) +#define push_includedir(_p) (_push_include((_p), TRUE)) /* realloc() to size + COMMANDARGINC to make room for command args */ #define COMMANDARGINC 64 @@ -227,6 +245,19 @@ DEFVAR [a-z_]+ yyterminate(); } +^#includedir[[:blank:]]+\/.*\n { + char *path; + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDEDIR\n"); + + /* Push current buffer and switch to include file */ + if (!push_includedir(path)) + yyterminate(); + } + ^[[:blank:]]*Defaults([:@>\!]{WORD})? { int n; for (n = 0; isblank((unsigned char)yytext[n]); n++) @@ -316,7 +347,7 @@ NOSETENV[[:blank:]]*: { return(NETGROUP); } -\%{WORD} { +\%:?{WORD} { /* UN*X group */ if (!fill(yytext, yyleng)) yyterminate(); @@ -412,11 +443,28 @@ sudoedit { } } /* a pathname */ +\"[^"\n]+\" { + /* a quoted user/group name */ + if (!fill(yytext + 1, yyleng - 2)) + yyterminate(); + switch (yytext[1]) { + case '%': + LEXTRACE("USERGROUP "); + return(USERGROUP); + case '+': + LEXTRACE("NETGROUP "); + return(NETGROUP); + default: + LEXTRACE("WORD(4) "); + return(WORD); + } + } + ({ID}|{WORD}) { /* a word */ if (!fill(yytext, yyleng)) yyterminate(); - LEXTRACE("WORD(4) "); + LEXTRACE("WORD(5) "); return(WORD); } @@ -467,12 +515,12 @@ sudoedit { LEXTRACE("\n\t"); } /* throw away EOL after \ */ -#([^\n0-9-].*)?\n { +#(-[^\n0-9].*|[^\n0-9-].*)?\n { BEGIN INITIAL; ++sudolineno; LEXTRACE("\n"); return(COMMENT); - } /* return comments */ + } /* comment, not uid/gid */ <*>. { LEXTRACE("ERROR "); @@ -490,12 +538,57 @@ sudoedit { } %% +static unsigned char +hexchar(s) + const char *s; +{ + int i; + int result = 0; + + s += 2; /* skip \\x */ + for (i = 0; i < 2; i++) { + switch (*s) { + case 'A': + case 'a': + result += 10; + break; + case 'B': + case 'b': + result += 11; + break; + case 'C': + case 'c': + result += 12; + break; + case 'D': + case 'd': + result += 13; + break; + case 'E': + case 'e': + result += 14; + break; + case 'F': + case 'f': + result += 15; + break; + default: + result += *s - '0'; + break; + } + if (i == 0) { + result *= 16; + s++; + } + } + return((unsigned char)result); +} + static int _fill(src, len, olen) char *src; int len, olen; { - int i, j; char *dst; dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); @@ -507,13 +600,24 @@ _fill(src, len, olen) /* Copy the string and collapse any escaped characters. */ dst += olen; - for (i = 0, j = 0; i < len; i++, j++) { - if (src[i] == '\\' && i != len - 1) - dst[j] = src[++i]; - else - dst[j] = src[i]; + while (len--) { + if (*src == '\\' && len) { + if (src[1] == 'x' && len >= 3 && + isxdigit((unsigned char) src[2]) && + isxdigit((unsigned char) src[3])) { + *dst++ = hexchar(src); + src += 4; + len -= 3; + } else { + src++; + len--; + *dst++ = *src++; + } + } else { + *dst++ = *src++; + } } - dst[j] = '\0'; + *dst = '\0'; return(TRUE); } @@ -605,63 +709,228 @@ fill_args(s, len, addspace) return(TRUE); } -struct sudoers_state { +struct path_list { + char *path; + struct path_list *next; +}; + +struct include_stack { YY_BUFFER_STATE bs; char *path; + struct path_list *more; /* more files in case of includedir */ int lineno; + int keepopen; }; +static int +pl_compare(v1, v2) + const void *v1; + const void *v2; +{ + const struct path_list * const *p1 = v1; + const struct path_list * const *p2 = v2; + + return(strcmp((*p1)->path, (*p2)->path)); +} + +static char * +switch_dir(stack, dirpath) + struct include_stack *stack; + char *dirpath; +{ + DIR *dir; + int i, count = 0; + char *path = NULL; + struct dirent *dent; + struct stat sb; + struct path_list *pl, *first = NULL; + struct path_list **sorted = NULL; + + if (!(dir = opendir(dirpath))) { + yyerror(dirpath); + return(FALSE); + } + while ((dent = readdir(dir))) { + /* Ignore files that end in '~' or have a '.' in them. */ + if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' + || strchr(dent->d_name, '.') != NULL) { + continue; + } + if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) { + closedir(dir); + goto bad; + } + if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) { + efree(path); + continue; + } + pl = malloc(sizeof(*pl)); + if (pl == NULL) + goto bad; + pl->path = path; + pl->next = first; + first = pl; + count++; + } + closedir(dir); + + if (count == 0) + goto done; + + /* Sort the list as an array. */ + sorted = malloc(sizeof(*sorted) * count); + if (sorted == NULL) + goto bad; + pl = first; + for (i = 0; i < count; i++) { + sorted[i] = pl; + pl = pl->next; + } + qsort(sorted, count, sizeof(*sorted), pl_compare); + + /* Apply sorting to the list. */ + first = sorted[0]; + sorted[count - 1]->next = NULL; + for (i = 1; i < count; i++) + sorted[i - 1]->next = sorted[i]; + efree(sorted); + + /* Pull out the first element for parsing, leave the rest for later. */ + if (count) { + path = first->path; + pl = first->next; + efree(first); + stack->more = pl; + } else { + path = NULL; + } +done: + efree(dirpath); + return(path); +bad: + while (first != NULL) { + pl = first; + first = pl->next; + free(pl->path); + free(pl); + } + efree(sorted); + efree(dirpath); + efree(path); + return(NULL); +} + #define MAX_SUDOERS_DEPTH 128 #define SUDOERS_STACK_INCREMENT 16 +static size_t istacksize, idepth; +static struct include_stack *istack; +static int keepopen; + +void +init_lexer() +{ + struct path_list *pl; + + while (idepth) { + idepth--; + while ((pl = istack[idepth].more) != NULL) { + istack[idepth].more = pl->next; + efree(pl->path); + efree(pl); + } + efree(istack[idepth].path); + if (!istack[idepth].keepopen) + fclose(istack[idepth].bs->yy_input_file); + yy_delete_buffer(istack[idepth].bs); + } + efree(istack); + istack = NULL; + istacksize = idepth = 0; + keepopen = FALSE; +} + static int -switch_buffer(path) +_push_include(path, isdir) char *path; + int isdir; { - static size_t stacksize, depth; - static struct sudoers_state *state; - static int keepopen; FILE *fp; - if (path != NULL) { - /* push current state */ - if (depth >= stacksize) { - if (depth > MAX_SUDOERS_DEPTH) { - yyerror("too many levels of includes"); - return(FALSE); - } - stacksize += SUDOERS_STACK_INCREMENT; - state = (struct sudoers_state *) realloc(state, - sizeof(state) * stacksize); - if (state == NULL) { - yyerror("unable to allocate memory"); - return(FALSE); - } + /* push current state onto stack */ + if (idepth >= istacksize) { + if (idepth > MAX_SUDOERS_DEPTH) { + yyerror("too many levels of includes"); + return(FALSE); + } + istacksize += SUDOERS_STACK_INCREMENT; + istack = (struct include_stack *) realloc(istack, + sizeof(istack) * istacksize); + if (istack == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); } - if ((fp = open_sudoers(path, &keepopen)) == NULL) { + } + if (isdir) { + if (!(path = switch_dir(&istack[idepth], path))) { yyerror(path); return(FALSE); } - state[depth].bs = YY_CURRENT_BUFFER; - state[depth].path = sudoers; - state[depth].lineno = sudolineno; - depth++; + if ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { + yyerror(path); + return(FALSE); /* XXX - just to go next one? */ + } + } else { + if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { + yyerror(path); + return(FALSE); + } + istack[idepth].more = NULL; + } + /* Push the old (current) file and open the new one. */ + istack[idepth].path = sudoers; /* push old path */ + istack[idepth].bs = YY_CURRENT_BUFFER; + istack[idepth].lineno = sudolineno; + istack[idepth].keepopen = keepopen; + idepth++; + sudolineno = 1; + sudoers = path; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + + return(TRUE); +} + +static int +pop_include() +{ + struct path_list *pl; + FILE *fp; + + if (idepth == 0) + return(FALSE); + + if (!keepopen) + fclose(YY_CURRENT_BUFFER->yy_input_file); + yy_delete_buffer(YY_CURRENT_BUFFER); + keepopen = FALSE; + if ((pl = istack[idepth - 1].more) != NULL) { + /* Move to next file in the dir. */ + istack[idepth - 1].more = pl->next; + if ((fp = open_sudoers(pl->path, FALSE, &keepopen)) == NULL) { + yyerror(pl->path); + return(FALSE); /* XXX - just to go next one? */ + } + efree(sudoers); + sudoers = pl->path; sudolineno = 1; - sudoers = path; yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + efree(pl); } else { - /* pop */ - if (depth == 0) - return(FALSE); - depth--; - if (!keepopen) - fclose(YY_CURRENT_BUFFER->yy_input_file); - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(state[depth].bs); + idepth--; + yy_switch_to_buffer(istack[idepth].bs); efree(sudoers); - sudoers = state[depth].path; - sudolineno = state[depth].lineno; - keepopen = FALSE; + sudoers = istack[idepth].path; + sudolineno = istack[idepth].lineno; } return(TRUE); } @@ -671,22 +940,45 @@ parse_include(base) char *base; { char *cp, *ep, *path; - int len; + int len = 0, subst = 0; + size_t shost_len = 0; /* Pull out path from #include line. */ cp = base + sizeof("#include"); + if (*cp == 'i') + cp += 3; /* includedir */ while (isblank((unsigned char) *cp)) cp++; ep = cp; - while (*ep != '\0' && !isspace((unsigned char) *ep)) + while (*ep != '\0' && !isspace((unsigned char) *ep)) { + if (ep[0] == '%' && ep[1] == 'h') { + shost_len = strlen(user_shost); + len += shost_len - 2; + subst = 1; + } ep++; + } /* Make a copy of path and return it. */ - len = (int)(ep - cp); + len += (int)(ep - cp); if ((path = malloc(len + 1)) == NULL) yyerror("unable to allocate memory"); - memcpy(path, cp, len); - path[len] = '\0'; + if (subst) { + /* substitute for %h */ + char *pp = path; + while (cp < ep) { + if (cp[0] == '%' && cp[1] == 'h') { + memcpy(pp, user_shost, shost_len); + pp += shost_len; + cp += 2; + } + *pp++ = *cp++; + } + *pp = '\0'; + } else { + memcpy(path, cp, len); + path[len] = '\0'; + } /* Push any excess characters (e.g. comment, newline) back to the lexer */ if (*ep != '\0') diff --git a/vasgroups.c b/vasgroups.c new file mode 100644 index 0000000..33a333d --- /dev/null +++ b/vasgroups.c @@ -0,0 +1,323 @@ +/* + * (c) 2006 Quest Software, 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: + * + * 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 Quest Software, 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 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. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "compat.h" +#include "logging.h" +#include "nonunix.h" +#include "parse.h" +#include "sudo.h" + + +/* Pseudo-boolean types */ +#undef TRUE +#undef FALSE +#define FALSE 0 +#define TRUE 1 + + +static vas_ctx_t *sudo_vas_ctx; +static vas_id_t *sudo_vas_id; +/* Don't use VAS_NAME_FLAG_NO_CACHE or lookups just won't work. + * -tedp, 2006-08-29 */ +static const int update_flags = 0; +static int sudo_vas_available = 0; +static char *err_msg = NULL; +static void *libvas_handle = NULL; + +/* libvas functions */ +static vas_err_t (*v_ctx_alloc) (vas_ctx_t **ctx); +static void (*v_ctx_free) (vas_ctx_t *ctx); +static vas_err_t (*v_id_alloc) (vas_ctx_t *ctx, const char *name, vas_id_t **id); +static void (*v_id_free) (vas_ctx_t *ctx, vas_id_t *id); +static vas_err_t (*v_id_establish_cred_keytab) (vas_ctx_t *ctx, vas_id_t *id, int credflags, const char *keytab); +static vas_err_t (*v_user_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_user_t **user); +static void (*v_user_free) (vas_ctx_t *ctx, vas_user_t *user); +static vas_err_t (*v_group_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_group_t **group); +static void (*v_group_free) (vas_ctx_t *ctx, vas_group_t *group); +static vas_err_t (*v_user_is_member) (vas_ctx_t *ctx, vas_id_t *id, vas_user_t *user, vas_group_t *group); +static const char* (*v_err_get_string) (vas_ctx_t *ctx, int with_cause); + + +static int resolve_vas_funcs(void); + + +/** + * Whether nonunix group lookups are available. + * @return 1 if available, 0 if not. + */ +int +sudo_nonunix_groupcheck_available(void) +{ + return sudo_vas_available; +} + + +/** + * Check if the user is in the group + * @param group group name which can be in DOMAIN\sam format or just the group + * name + * @param user user name + * @param pwd (unused) + * @return 1 if user is a member of the group, 0 if not (or error occurred) + */ +int +sudo_nonunix_groupcheck( const char* group, const char* user, const struct passwd* pwd ) +{ + static int error_cause_shown = FALSE; + int rval = FALSE; + vas_err_t vaserr; + vas_user_t* vas_user = NULL; + vas_group_t* vas_group = NULL; + + if (!sudo_vas_available) { + if (error_cause_shown == FALSE) { + /* Produce the saved error reason */ + log_error(NO_MAIL|NO_EXIT, "Non-unix group checking unavailable: %s", + err_msg ? err_msg + : "(unknown cause)"); + error_cause_shown = TRUE; + } + return 0; + } + + /* resolve the user and group. The user will be a real Unix account name, + * while the group may be a unix name, or any group name accepted by + * vas_name_to_dn, which means any of: + * - Group Name + * - Group Name@FULLY.QUALIFIED.DOMAIN + * - CN=sudoers,CN=Users,DC=rcdev,DC=vintela,DC=com + * - S-1-2-34-5678901234-5678901234-5678901234-567 + * + * XXX - we may get non-VAS user accounts here. You can add local users to an + * Active Directory group through override files. Should we handle that case? + * */ + if( (vaserr = v_user_init( sudo_vas_ctx, sudo_vas_id, user, update_flags, &vas_user )) != VAS_ERR_SUCCESS ) { + if (vaserr == VAS_ERR_NOT_FOUND) { + /* No such user in AD. Probably a local user. */ + vaserr = VAS_ERR_SUCCESS; + } + goto FINISHED; + } + + if( (vaserr = v_group_init( sudo_vas_ctx, sudo_vas_id, group, update_flags, &vas_group )) != VAS_ERR_SUCCESS ) { + goto FINISHED; + } + + /* do the membership check */ + if( (vaserr = v_user_is_member( sudo_vas_ctx, sudo_vas_id, vas_user, vas_group )) == VAS_ERR_SUCCESS ) { + rval = TRUE; + } + else if (vaserr == VAS_ERR_NOT_FOUND) { + /* fake the vaserr code so no error is triggered */ + vaserr = VAS_ERR_SUCCESS; + } + + +FINISHED: /* cleanups */ + if (vaserr != VAS_ERR_SUCCESS) { + int error_flags = NO_MAIL | MSG_ONLY | (uses_inversion ? 0 : NO_EXIT); + + log_error(error_flags, "Error while checking group membership " + "for user \"%s\", group \"%s\", error: %s%s.", user, group, + v_err_get_string(sudo_vas_ctx, 1), + /* A helpful hint if there seems to be a non-FQDN as the domain */ + (strchr(group, '@') && !strchr(group, '.')) + ? "\nMake sure the fully qualified domain name is specified" + : ""); + } + if( vas_group ) v_group_free( sudo_vas_ctx, vas_group ); + if( vas_user ) v_user_free( sudo_vas_ctx, vas_user ); + + return(rval); +} + + +static void +set_err_msg(const char *msg, ...) { + va_list ap; + + if (!msg) /* assert */ + return; + + if (err_msg) + free(err_msg); + + va_start(ap, msg); + + if (vasprintf(&err_msg, msg, ap) == -1) + err_msg = NULL; + + va_end(ap); +} + + +/** + * Initialise nonunix_groupcheck state. + */ +void +sudo_nonunix_groupcheck_init(void) +{ + vas_err_t vaserr; + void *libvas; + + if (err_msg) { + free(err_msg); + err_msg = NULL; + } + + libvas = dlopen(LIBVAS_SO, RTLD_LAZY); + if (!libvas) { + set_err_msg("dlopen() failed: %s", dlerror()); + return; + } + + libvas_handle = libvas; + + if (resolve_vas_funcs() != 0) + return; + + if (VAS_ERR_SUCCESS == (vaserr = v_ctx_alloc(&sudo_vas_ctx))) { + + if (VAS_ERR_SUCCESS == (vaserr = v_id_alloc(sudo_vas_ctx, "host/", &sudo_vas_id))) { + + if (update_flags & VAS_NAME_FLAG_NO_LDAP) { + sudo_vas_available = 1; + return; /* OK */ + } else { /* Get a keytab */ + if ((vaserr = v_id_establish_cred_keytab( sudo_vas_ctx, + sudo_vas_id, + VAS_ID_FLAG_USE_MEMORY_CCACHE + | VAS_ID_FLAG_KEEP_COPY_OF_CRED + | VAS_ID_FLAG_NO_INITIAL_TGT, + NULL )) == VAS_ERR_SUCCESS) { + sudo_vas_available = 1; + return; /* OK */ + } + + if (!err_msg) + set_err_msg("unable to establish creds: %s", + v_err_get_string(sudo_vas_ctx, 1)); + } + + v_id_free(sudo_vas_ctx, sudo_vas_id); + sudo_vas_id = NULL; + } + + /* This is the last opportunity to get an error message from libvas */ + if (!err_msg) + set_err_msg("Error initializing non-unix group checking: %s", + v_err_get_string(sudo_vas_ctx, 1)); + + v_ctx_free(sudo_vas_ctx); + sudo_vas_ctx = NULL; + } + + if (!err_msg) + set_err_msg("Failed to get a libvas handle for non-unix group checking (unknown cause)"); + + sudo_vas_available = 0; +} + + +/** + * Clean up nonunix_groupcheck state. + */ +void +sudo_nonunix_groupcheck_cleanup() +{ + if (err_msg) { + free(err_msg); + err_msg = NULL; + } + + if (sudo_vas_available) { + v_id_free(sudo_vas_ctx, sudo_vas_id); + sudo_vas_id = NULL; + + v_ctx_free(sudo_vas_ctx); + sudo_vas_ctx = NULL; + + sudo_vas_available = FALSE; + } + + if (libvas_handle) { + if (dlclose(libvas_handle) != 0) + log_error(NO_MAIL|NO_EXIT, "dlclose() failed: %s", dlerror()); + libvas_handle = NULL; + } +} + +#define RESOLVE_OR_ERR(fptr, sym) \ + do { \ + void *_fptr = dlsym(libvas_handle, (sym)); \ + if (!_fptr) { \ + set_err_msg("dlsym() failed: %s", dlerror()); \ + return -1; \ + } \ + fptr = _fptr; \ + } while (0) + + +/** + * Resolve all the libvas functions. + * Returns -1 and sets err_msg if something went wrong, or 0 on success. + */ +int +resolve_vas_funcs(void) +{ + if (!libvas_handle) /* assert */ + return -1; + + RESOLVE_OR_ERR(v_ctx_alloc, "vas_ctx_alloc"); + RESOLVE_OR_ERR(v_ctx_free, "vas_ctx_free"); + RESOLVE_OR_ERR(v_id_alloc, "vas_id_alloc"); + RESOLVE_OR_ERR(v_id_free, "vas_id_free"); + RESOLVE_OR_ERR(v_id_establish_cred_keytab, "vas_id_establish_cred_keytab"); + RESOLVE_OR_ERR(v_user_init, "vas_user_init"); + RESOLVE_OR_ERR(v_user_free, "vas_user_free"); + RESOLVE_OR_ERR(v_group_init, "vas_group_init"); + RESOLVE_OR_ERR(v_group_free, "vas_group_free"); + RESOLVE_OR_ERR(v_user_is_member, "vas_user_is_member"); + RESOLVE_OR_ERR(v_err_get_string, "vas_err_get_string"); + + return 0; +} diff --git a/visudo.c b/visudo.c index 81b5718..b48fc24 100644 --- a/visudo.c +++ b/visudo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -83,19 +83,20 @@ #include "sudo.h" #include "interfaces.h" #include "parse.h" +#include "redblack.h" #include -#include "version.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: visudo.c,v 1.223 2008/11/22 15:12:26 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: visudo.c,v 1.234 2009/05/25 12:02:42 millert Exp $"; #endif /* lint */ struct sudoersfile { char *path; - int fd; char *tpath; + int fd; int tfd; int modified; + int doedit; struct sudoersfile *next; }; @@ -105,14 +106,16 @@ struct sudoersfile { static RETSIGTYPE quit __P((int)); static char *get_args __P((char *)); static char *get_editor __P((char **)); +static void get_hostname __P((void)); static char whatnow __P((void)); -static int check_aliases __P((int)); +static int check_aliases __P((int, int)); static int check_syntax __P((char *, int, int)); static int edit_sudoers __P((struct sudoersfile *, char *, char *, int)); static int install_sudoers __P((struct sudoersfile *, int)); static int print_unused __P((void *, void *)); static int reparse_sudoers __P((char *, char *, int, int)); static int run_command __P((char *, char **)); +static void print_undefined __P((char *name, int, int, int)); static void setup_signals __P((void)); static void usage __P((void)) __attribute__((__noreturn__)); @@ -122,6 +125,7 @@ extern void yyrestart __P((FILE *)); /* * External globals exported by the parser */ +extern struct rbtree *aliases; extern FILE *yyin; extern char *sudoers, *errorfile; extern int errorlineno, parse_error; @@ -141,6 +145,7 @@ struct passwd *list_pw; static struct sudoerslist { struct sudoersfile *first, *last; } sudoerslist; +static struct rbtree *alias_freelist; int main(argc, argv) @@ -167,7 +172,7 @@ main(argc, argv) while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) { switch (ch) { case 'V': - (void) printf("%s version %s\n", getprogname(), version); + (void) printf("%s version %s\n", getprogname(), PACKAGE_VERSION); exit(0); case 'c': checkonly++; /* check mode */ @@ -195,9 +200,10 @@ main(argc, argv) sudo_setgrent(); /* Mock up a fake sudo_user struct. */ - user_host = user_shost = user_cmnd = ""; + user_cmnd = ""; if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) errorx(1, "you don't exist in the passwd database"); + get_hostname(); /* Setup defaults data structures. */ init_defaults(); @@ -209,8 +215,9 @@ main(argc, argv) * Parse the existing sudoers file(s) in quiet mode to highlight any * existing errors and to pull in editor and env_editor conf values. */ - if ((yyin = open_sudoers(sudoers_path, NULL)) == NULL) + if ((yyin = open_sudoers(sudoers_path, TRUE, NULL)) == NULL) { error(1, "%s", sudoers_path); + } init_parser(sudoers_path, 0); yyparse(); (void) update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER); @@ -222,6 +229,8 @@ main(argc, argv) /* Edit the sudoers file(s) */ tq_foreach_fwd(&sudoerslist, sp) { + if (!sp->doedit) + continue; if (sp != tq_first(&sudoerslist)) { printf("press return to edit %s: ", sp->path); while ((ch = getchar()) != EOF && ch != '\n') @@ -428,7 +437,7 @@ reparse_sudoers(editor, args, strict, quiet) parse_error = TRUE; } fclose(yyin); - if (check_aliases(strict) != 0) + if (check_aliases(strict, quiet) != 0) parse_error = TRUE; /* @@ -698,10 +707,14 @@ check_syntax(sudoers_path, quiet, strict) warningx("failed to parse %s file, unknown error", sudoers_path); parse_error = TRUE; } + if (!parse_error) { + if (check_aliases(strict, quiet) != 0) + parse_error = TRUE; + } error = parse_error; if (!quiet) { if (parse_error) - (void) printf("parse error in %s near line %d\n", sudoers_path, + (void) printf("parse error in %s near line %d\n", errorfile, errorlineno); else (void) printf("%s: parsed OK\n", sudoers_path); @@ -737,8 +750,9 @@ check_syntax(sudoers_path, quiet, strict) * any subsequent files #included via a callback from the parser. */ FILE * -open_sudoers(path, keepopen) +open_sudoers(path, doedit, keepopen) const char *path; + int doedit; int *keepopen; { struct sudoersfile *entry; @@ -756,6 +770,8 @@ open_sudoers(path, keepopen) entry->next = NULL; entry->fd = open(entry->path, O_RDWR | O_CREAT, SUDOERS_MODE); entry->tpath = NULL; + entry->tfd = -1; + entry->doedit = doedit; if (entry->fd == -1) { warning("%s", entry->path); efree(entry); @@ -772,8 +788,6 @@ open_sudoers(path, keepopen) sudoerslist.last->next = entry; sudoerslist.last = entry; } - if (keepopen != NULL) - *keepopen = TRUE; } else { /* Already exists, open .tmp version if there is one. */ if (entry->tpath != NULL) { @@ -782,8 +796,11 @@ open_sudoers(path, keepopen) } else { if ((fp = fdopen(entry->fd, "r")) == NULL) error(1, "%s", entry->path); + rewind(fp); } } + if (keepopen != NULL) + *keepopen = TRUE; return(fp); } @@ -908,13 +925,59 @@ get_args(cmnd) return(*args ? args : NULL); } +/* + * Look up the hostname and set user_host and user_shost. + */ +static void +get_hostname() +{ + char *p, thost[MAXHOSTNAMELEN + 1]; + + if (gethostname(thost, sizeof(thost)) != 0) { + user_host = user_shost = "localhost"; + return; + } + thost[sizeof(thost) - 1] = '\0'; + user_host = estrdup(thost); + + if ((p = strchr(user_host, '.'))) { + *p = '\0'; + user_shost = estrdup(user_host); + *p = '.'; + } else { + user_shost = user_host; + } +} + +static void +alias_remove_recursive(name, type) + char *name; + int type; +{ + struct member *m; + struct alias *a; + + if ((a = alias_find(name, type)) != NULL) { + tq_foreach_fwd(&a->members, m) { + if (m->type == ALIAS) { + alias_remove_recursive(m->name, type); + } + } + } + alias_seqno++; + a = alias_remove(name, type); + if (a) + rbinsert(alias_freelist, a); +} + /* * Iterate through the sudoers datastructures looking for undefined * aliases or unused aliases. */ static int -check_aliases(strict) +check_aliases(strict, quiet) int strict; + int quiet; { struct cmndspec *cs; struct member *m, *binding; @@ -923,14 +986,15 @@ check_aliases(strict) struct defaults *d; int atype, error = 0; + alias_freelist = rbcreate(alias_compare); + /* Forward check. */ tq_foreach_fwd(&userspecs, us) { tq_foreach_fwd(&us->users, m) { if (m->type == ALIAS) { alias_seqno++; - if (find_alias(m->name, USERALIAS) == NULL) { - warningx("%s: User_Alias `%s' referenced but not defined", - strict ? "Error" : "Warning", m->name); + if (alias_find(m->name, USERALIAS) == NULL) { + print_undefined(m->name, USERALIAS, strict, quiet); error++; } } @@ -939,9 +1003,8 @@ check_aliases(strict) tq_foreach_fwd(&priv->hostlist, m) { if (m->type == ALIAS) { alias_seqno++; - if (find_alias(m->name, HOSTALIAS) == NULL) { - warningx("%s: Host_Alias `%s' referenced but not defined", - strict ? "Error" : "Warning", m->name); + if (alias_find(m->name, HOSTALIAS) == NULL) { + print_undefined(m->name, HOSTALIAS, strict, quiet); error++; } } @@ -950,18 +1013,16 @@ check_aliases(strict) tq_foreach_fwd(&cs->runasuserlist, m) { if (m->type == ALIAS) { alias_seqno++; - if (find_alias(m->name, RUNASALIAS) == NULL) { - warningx("%s: Runas_Alias `%s' referenced but not defined", - strict ? "Error" : "Warning", m->name); + if (alias_find(m->name, RUNASALIAS) == NULL) { + print_undefined(m->name, RUNASALIAS, strict, quiet); error++; } } } if ((m = cs->cmnd)->type == ALIAS) { alias_seqno++; - if (find_alias(m->name, CMNDALIAS) == NULL) { - warningx("%s: Cmnd_Alias `%s' referenced but not defined", - strict ? "Error" : "Warning", m->name); + if (alias_find(m->name, CMNDALIAS) == NULL) { + print_undefined(m->name, CMNDALIAS, strict, quiet); error++; } } @@ -972,21 +1033,22 @@ check_aliases(strict) /* Reverse check (destructive) */ tq_foreach_fwd(&userspecs, us) { tq_foreach_fwd(&us->users, m) { - if (m->type == ALIAS) - (void) alias_remove(m->name, USERALIAS); + if (m->type == ALIAS) { + (void) alias_remove_recursive(m->name, USERALIAS); + } } tq_foreach_fwd(&us->privileges, priv) { tq_foreach_fwd(&priv->hostlist, m) { if (m->type == ALIAS) - (void) alias_remove(m->name, HOSTALIAS); + (void) alias_remove_recursive(m->name, HOSTALIAS); } tq_foreach_fwd(&priv->cmndlist, cs) { tq_foreach_fwd(&cs->runasuserlist, m) { if (m->type == ALIAS) - (void) alias_remove(m->name, RUNASALIAS); + (void) alias_remove_recursive(m->name, RUNASALIAS); } if ((m = cs->cmnd)->type == ALIAS) - (void) alias_remove(m->name, CMNDALIAS); + (void) alias_remove_recursive(m->name, CMNDALIAS); } } } @@ -1010,18 +1072,37 @@ check_aliases(strict) tq_foreach_fwd(&d->binding, binding) { for (m = binding; m != NULL; m = m->next) { if (m->type == ALIAS) - (void) alias_remove(m->name, atype); + (void) alias_remove_recursive(m->name, atype); } } } + rbdestroy(alias_freelist, alias_free); /* If all aliases were referenced we will have an empty tree. */ if (no_aliases()) return(0); - alias_apply(print_unused, strict ? "Error" : "Warning"); + if (!quiet) { + alias_apply(print_unused, strict ? "Error" : "Warning"); + } return (strict ? 1 : 0); } +static void +print_undefined(name, type, strict, quiet) + char *name; + int type; + int strict; + int quiet; +{ + if (!quiet) { + warningx("%s: %s_Alias `%s' referenced but not defined", + strict ? "Error" : "Warning", + type == HOSTALIAS ? "Host" : type == CMNDALIAS ? "Cmnd" : + type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" : + "Unknown", name); + } +} + static int print_unused(v1, v2) void *v1; diff --git a/visudo.cat b/visudo.cat index 74be714..51c822e 100644 --- a/visudo.cat +++ b/visudo.cat @@ -53,15 +53,15 @@ OOPPTTIIOONNSS -f _s_u_d_o_e_r_s Specify and alternate _s_u_d_o_e_r_s file location. With this option vviissuuddoo will edit (or check) the _s_u_d_o_e_r_s file of your - choice, instead of the default, _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s. The - lock file used is the specified _s_u_d_o_e_r_s file with ".tmp" + choice, instead of the default, _/_e_t_c_/_s_u_d_o_e_r_s. The lock + file used is the specified _s_u_d_o_e_r_s file with ".tmp" appended to it. -q Enable qquuiieett mode. In this mode details about syntax -1.7.0 November 15, 2008 1 +1.7.2 June 11, 2009 1 @@ -92,10 +92,9 @@ EENNVVIIRROONNMMEENNTT EDITOR Used by visudo if VISUAL is not set FFIILLEESS - _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s List of who can run what + _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what - _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s_._t_m_p - Lock file for visudo + _/_e_t_c_/_s_u_d_o_e_r_s_._t_m_p Lock file for visudo DDIIAAGGNNOOSSTTIICCSS sudoers file busy, try again later. @@ -123,11 +122,12 @@ DDIIAAGGNNOOSSTTIICCSS SSEEEE AALLSSOO _v_i(1), _s_u_d_o_e_r_s(4), _s_u_d_o(1m), _v_i_p_w(8) +AAUUTTHHOORR + Many people have worked on _s_u_d_o over the years; this version of vviissuuddoo - -1.7.0 November 15, 2008 2 +1.7.2 June 11, 2009 2 @@ -136,8 +136,6 @@ SSEEEE AALLSSOO VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) -AAUUTTHHOORR - Many people have worked on _s_u_d_o over the years; this version of vviissuuddoo was written by: Todd Miller @@ -193,6 +191,8 @@ DDIISSCCLLAAIIMMEERR -1.7.0 November 15, 2008 3 + + +1.7.2 June 11, 2009 3 diff --git a/visudo.man.in b/visudo.man.in index 7aa576b..dc33f54 100644 --- a/visudo.man.in +++ b/visudo.man.in @@ -18,7 +18,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.\" $Sudo: visudo.man.in,v 1.32 2008/11/15 18:34:26 millert Exp $ +.\" $Sudo: visudo.man.in,v 1.34 2009/06/11 20:29:12 millert Exp $ .\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: @@ -153,7 +153,7 @@ .\" ======================================================================== .\" .IX Title "VISUDO @mansectsu@" -.TH VISUDO @mansectsu@ "November 15, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.TH VISUDO @mansectsu@ "June 11, 2009" "1.7.2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -211,7 +211,7 @@ exit with a value of 0. If a syntax error is encountered, .IX Item "-f sudoers" Specify and alternate \fIsudoers\fR file location. With this option \&\fBvisudo\fR will edit (or check) the \fIsudoers\fR file of your choice, -instead of the default, \fI\f(CI@sysconfdir\fI@/sudoers\fR. The lock file used +instead of the default, \fI@sysconfdir@/sudoers\fR. The lock file used is the specified \fIsudoers\fR file with \*(L".tmp\*(R" appended to it. .IP "\-q" 12 .IX Item "-q" @@ -243,12 +243,12 @@ Invoked by visudo as the editor to use Used by visudo if \s-1VISUAL\s0 is not set .SH "FILES" .IX Header "FILES" -.ie n .IP "\fI\fI@sysconfdir\fI@/sudoers\fR" 24 -.el .IP "\fI\f(CI@sysconfdir\fI@/sudoers\fR" 24 +.ie n .IP "\fI@sysconfdir@/sudoers\fR" 24 +.el .IP "\fI@sysconfdir@/sudoers\fR" 24 .IX Item "@sysconfdir@/sudoers" List of who can run what -.ie n .IP "\fI\fI@sysconfdir\fI@/sudoers.tmp\fR" 24 -.el .IP "\fI\f(CI@sysconfdir\fI@/sudoers.tmp\fR" 24 +.ie n .IP "\fI@sysconfdir@/sudoers.tmp\fR" 24 +.el .IP "\fI@sysconfdir@/sudoers.tmp\fR" 24 .IX Item "@sysconfdir@/sudoers.tmp" Lock file for visudo .SH "DIAGNOSTICS" -- 2.30.2